主要内容:
- 数据拼接: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