Python数据分析_Pandas02_数据框的合并和重整

主要内容:
  • 数据拼接:join、merge、contact、append
  • 数据重整:reshape -- stuck、unstuck
  • 数据透视表:pivot tables

数据拼接

1. concat

参数介绍:

pd.concat(objs, axis=0, join='outer', join_axes=None, ignore_index=False,
          keys=None, levels=None, names=None, verify_integrity=False,
          copy=True)

axis:要粘在哪个轴上。默认0,粘贴行。
join:默认outer,合集;inner,交集。
ignore_index:布尔型,默认False。如果为Ture的话,会重新分配index从0...n-1。
keys:一个序列,默认None。建立等级索引,作为最外层的level。
levels:序列sequences构成的list,默认None。

示例:

In [41]: df1 = pd.DataFrame({'A': ['A0', 'A1', 'A2', 'A3'],
    ...:                     'B': ['B0', 'B1', 'B2', 'B3'],
    ...:                     'C': ['C0', 'C1', 'C2', 'C3'],
    ...:                     'D': ['D0', 'D1', 'D2', 'D3']},
    ...:                     index=[0, 1, 2, 3])

In [42]: df2 = pd.DataFrame({'A': ['A4', 'A5', 'A6', 'A7'],
    ...:                     'B': ['B4', 'B5', 'B6', 'B7'],
    ...:                     'C': ['C4', 'C5', 'C6', 'C7'],
    ...:                     'D': ['D4', 'D5', 'D6', 'D7']},
    ...:                      index=[4, 5, 6, 7])
    ...:

In [43]: df3 = pd.DataFrame({'A': ['A8', 'A9', 'A10', 'A11'],
    ...:                     'B': ['B8', 'B9', 'B10', 'B11'],
    ...:                     'C': ['C8', 'C9', 'C10', 'C11'],
    ...:                     'D': ['D8', 'D9', 'D10', 'D11']},
    ...:                     index=[8, 9, 10, 11])
    ...:

In [44]: frames = [df1, df2, df3]

In [45]: result = pd.concat(frames)

In [46]: result
Out[46]:
      A    B    C    D
0    A0   B0   C0   D0
1    A1   B1   C1   D1
2    A2   B2   C2   D2
3    A3   B3   C3   D3
4    A4   B4   C4   D4
5    A5   B5   C5   D5
6    A6   B6   C6   D6
7    A7   B7   C7   D7
8    A8   B8   C8   D8
9    A9   B9   C9   D9
10  A10  B10  C10  D10
11  A11  B11  C11  D11

In [47]:  result2 = pd.concat(frames, keys=['x', 'y', 'z'])

In [48]: result2
Out[48]:
        A    B    C    D
x 0    A0   B0   C0   D0
  1    A1   B1   C1   D1
  2    A2   B2   C2   D2
  3    A3   B3   C3   D3
y 4    A4   B4   C4   D4
  5    A5   B5   C5   D5
  6    A6   B6   C6   D6
  7    A7   B7   C7   D7
z 8    A8   B8   C8   D8
  9    A9   B9   C9   D9
  10  A10  B10  C10  D10
  11  A11  B11  C11  D11

In [51]: result2.index    # result2的shape是(12,4),多重索引,如下:
Out[51]:
MultiIndex(levels=[['x', 'y', 'z'], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]],
           labels=[[0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]])

In [49]: result2.ix['y']                # .ix 等级索引
Out[49]:
    A   B   C   D
4  A4  B4  C4  D4
5  A5  B5  C5  D5
6  A6  B6  C6  D6
7  A7  B7  C7  D7

contact会生成一个copy,比较费内存。如果要用的话,最好把所有要拼接的数据框放一list中,一次concat所有。像这样:

frames = [ process_your_file(f) for f in files ]
result = pd.concat(frames)

2. append

和python中list的append不同,这里的append不改变原来的数据框,返回一个拼接后的copy。

In [57]: appended = df1.append([df2, df3])

In [58]: appended
Out[58]:
      A    B    C    D
0    A0   B0   C0   D0
1    A1   B1   C1   D1
2    A2   B2   C2   D2
3    A3   B3   C3   D3
4    A4   B4   C4   D4
5    A5   B5   C5   D5
6    A6   B6   C6   D6
7    A7   B7   C7   D7
8    A8   B8   C8   D8
9    A9   B9   C9   D9
10  A10  B10  C10  D10
11  A11  B11  C11  D11

In [59]: df1
Out[59]:
    A   B   C   D
0  A0  B0  C0  D0
1  A1  B1  C1  D1
2  A2  B2  C2  D2
3  A3  B3  C3  D3

添加一行:【注】ignore_index=True

可以添加Series或list(放着dicts的list)

In [80]: s2 = pd.Series(['X0', 'X1', 'X2', 'X3'],index=df1.columns)
In [83]: df1_s2 =  df1.append(s2,ignore_index=True)

In [84]: df1_s2
Out[84]:
    A   B   C   D
0  A0  B0  C0  D0
1  A1  B1  C1  D1
2  A2  B2  C2  D2
3  A3  B3  C3  D3
4  X0  X1  X2  X3

dicts = [{'A': 1, 'B': 2, 'C': 3, 'X': 4},
         {'A': 5, 'B': 6, 'C': 7, 'Y': 8}]
result = df1.append(dicts, ignore_index=True)

下面的merge和join是针对数据框合并的,一般都是列合并。

3. merge

参数介绍:

pd.merge(left, right, how='inner', on=None, left_on=None, right_on=None,
         left_index=False, right_index=False, sort=True,
         suffixes=('_x', '_y'), copy=True, indicator=False)
         
left: 一个dataframe对象
right: 另一个dataframe对象
how: 可以是'left', 'right', 'outer', 'inner'. 默认为inner。
on: 列名,两个dataframe都有的列。如果不传参数,
    而且left_index和right_index也等于False,
    则默认把两者交叉/共有的列作为链接键(join keys)。
    可以是一个列名,也可以是包含多个列名的list。
left_on: 左边dataframe的列会用做keys。可以是列名,
    或者与dataframe长度相同的矩阵array。
right_on: 右边同上。
left_index: 如果为Ture,用左侧dataframe的index作为
    连接键。如果是多维索引,level数要跟右边相同才行。
right_index: 右边同上。
sort: 对合并后的数据框排序,以连接键。
suffixes: 一个tuple,包字符串后缀,用来加在重叠的列名后面。
    默认是('_x','_y')。
copy: 默认Ture,复制数据。
indicator: 布尔型(True/FALSE),或是字符串。
    如果为True,合并之后会增加一列叫做'_merge'。
    是分类数据,用left_only, right_only, both来标记
    来自左边,右边和两边的数据。

示例:

In [4]: left = pd.DataFrame({'key': ['K0', 'K1', 'K2', 'K3'],
   ...:                      'A': ['A0', 'A1', 'A2', 'A3'],
   ...:                      'B': ['B0', 'B1', 'B2', 'B3']})
   ...:

In [6]: right = pd.DataFrame({'key': ['K1', 'K2', 'K3', 'K4'],
   ...:                       'C': ['C0', 'C1', 'C2', 'C3'],
   ...:                       'D': ['D0', 'D1', 'D2', 'D3']})
   ...:

#默认inner合并,只保留共同的部分。
In [7]: pd.merge(left, right, on='key')
Out[7]:
    A   B key   C   D
0  A1  B1  K1  C0  D0
1  A2  B2  K2  C1  D1
2  A3  B3  K3  C2  D2

#outer方式合并
In [8]: pd.merge(left, right, how='outer', on='key')
Out[8]:
     A    B key    C    D
0   A0   B0  K0  NaN  NaN
1   A1   B1  K1   C0   D0
2   A2   B2  K2   C1   D1
3   A3   B3  K3   C2   D2
4  NaN  NaN  K4   C3   D3

#indicator,用来标示数据来源。
In [11]: In [8]: pd.merge(left, right, how='outer', on='key', indicator = 'indicator_colomn')
Out[11]:
     A    B key    C    D indicator_colomn
0   A0   B0  K0  NaN  NaN        left_only
1   A1   B1  K1   C0   D0             both
2   A2   B2  K2   C1   D1             both
3   A3   B3  K3   C2   D2             both
4  NaN  NaN  K4   C3   D3       right_only

4. Join

另一个便捷的合并数据框的方法。

参数介绍:

DataFrame.join(other, on=None, how='left', lsuffix='', rsuffix='', sort=False)

other:一个DataFrame、Series(要有命名),或者DataFrame组成的list。
on:列名,包含列名的list或tuple,或矩阵样子的列
    (如果是多列,必须有MultiIndex)。
    跟上面的几种方法一样,用来指明依据哪一列进行合并。
    如果没有赋值,则依据两个数据框的index合并。
how:合并方式, {‘left’, ‘right’, ‘outer’, ‘inner’},
    默认 ‘left’调用函数的数据框。
lsuffix:字符串。用于左侧数据框的重复列。
    把重复列重新命名,原来的列名+字符串。
    【如果有重复列,必须添加这个参数。】
rsuffix:同上。右侧。
sort:布尔型,默认False。如果为True,将链接键(on的那列)按字母排序。

示例:

In [3]: left = pd.DataFrame({'A': ['A0', 'A1', 'A2'],
   ...:                      'B': ['B0', 'B1', 'B2'],
   ...:                      'D': ['D3', 'D4', 'D5']},
   ...:                      index=['K0', 'K1', 'K2'])
   ...:
   ...: right = pd.DataFrame({'C': ['C0', 'C2', 'C3'],
   ...:                       'D': ['D0', 'D2', 'D3']},
   ...:                       index=['K0', 'K2', 'K3'])
   ...:
   
In [5]: left.join(right, lsuffix='_left', rsuffix='_right')
Out[5]:
     A   B D_left    C D_right
K0  A0  B0     D3   C0      D0
K1  A1  B1     D4  NaN     NaN
K2  A2  B2     D5   C2      D2

In [8]: left.join(right, on='D', how='outer', lsuffix='_left', rsuffix='_right')
Out[8]:
     D    A    B D_left    C D_right
K0  D3   A0   B0     D3  NaN     NaN
K1  D4   A1   B1     D4  NaN     NaN
K2  D5   A2   B2     D5  NaN     NaN
K2  K0  NaN  NaN    NaN   C0      D0
K2  K2  NaN  NaN    NaN   C2      D2
K2  K3  NaN  NaN    NaN   C3      D3

#对比没有'on'的情况。对于上面第8行输出有点儿懵逼。
In [9]: left.join(right, how='outer', lsuffix='_left', rsuffix='_right')
Out[9]:
      A    B D_left    C D_right
K0   A0   B0     D3   C0      D0
K1   A1   B1     D4  NaN     NaN
K2   A2   B2     D5   C2      D2
K3  NaN  NaN    NaN   C3      D3

# 使用默认索引的时候:
In [10]: left = pd.DataFrame({'A': ['A0', 'A1', 'A2'],
    ...:                      'B': ['B0', 'B1', 'B2'],
    ...:                      'D': ['D3', 'D4', 'D5']})
    ...: right = pd.DataFrame({'C': ['C0', 'C2', 'C3'],
    ...:                       'D': ['D0', 'D2', 'D3']})
    ...:

In [11]: left.join(right, lsuffix='_left', rsuffix='_right')
Out[11]:
    A   B D_left   C D_right
0  A0  B0     D3  C0      D0
1  A1  B1     D4  C2      D2
2  A2  B2     D5  C3      D3

合并数据框这些方法大同小异,选一个能满足需要就行啦。


数据重整

pivot

用于生成一个数据透视表。

参数介绍:

DataFrame.pivot(index=None, columns=None, values=None)[source]

index:字符串或对象,可选。列名,用来当新数据框index的列,可以是多个列名的list。
columns:字符串或对象。列名,当做新数据框的列。
values:字符串或对象,可选。列名,生成新数据框的值。
    如果没有指定,则使用余下的所有列,会生成等级索引列。

示例:

In [16]: df = pd.DataFrame({'foo': ['one','one','one','two','two','two'],
    ...:                    'bar': ['A', 'B', 'C', 'A', 'B', 'C'],
    ...:                    'baz': [1, 2, 3, 4, 5, 6]})

In [20]: df
Out[20]:
  bar  baz  foo
0   A    1  one
1   B    2  one
2   C    3  one
3   A    4  two
4   B    5  two
5   C    6  two

In [21]: df.pivot(index='foo', columns='bar', values='baz')
    ...:
Out[21]:
bar  A  B  C
foo
one  1  2  3
two  4  5  6

# 有多列数值的情况
In [22]: df['baz_2'] = df['baz']*2

In [23]: df.pivot(index='foo', columns='bar')
Out[23]:
    baz       baz_2
bar   A  B  C     A   B   C
foo
one   1  2  3     2   4   6
two   4  5  6     8  10  12

# 另一种选择数值value的方法
In [24]: df.pivot(index='foo', columns='bar')['baz_2']
Out[24]:
bar  A   B   C
foo
one  2   4   6
two  8  10  12

升级版pivot:pandas.DataFrame.pivot_table。有更多的参数。个人感觉比较鸡肋,复杂的分类汇总有其他的函数可用。

stack 和 unstack

另一种重整数据的方法。stack和unstack是互逆方式。参数很简单。直接贴个例子好了

In [41]: df2 = df.pivot(index='foo', columns='bar')['baz_2']
    ...: df2
    ...:
Out[41]:
bar  A   B   C
foo
one  2   4   6
two  8  10  12

In [42]: stacked = df2.stack()

In [43]: stacked
Out[43]:
foo  bar
one  A       2
     B       4
     C       6
two  A       8
     B      10
     C      12
dtype: int64

In [44]: stacked.unstack()
Out[44]:
bar  A   B   C
foo
one  2   4   6
two  8  10  12
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,386评论 6 479
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,939评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,851评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,953评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,971评论 5 369
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,784评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,126评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,765评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,148评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,744评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,858评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,479评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,080评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,053评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,278评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,245评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,590评论 2 343

推荐阅读更多精彩内容