赞
踩
简介
pandas提供了一套合并数据集操作的方法:
pandas.merge()可根据一个或者多个键将不同的DataFrame连接在一起,类似于SQL数据库中的合并操作;
pandas.concat()可以沿某个轴将多个数据集连接在一起。
接下来将分别对这两种方法进行介绍。
merge()函数
merge()函数中的参数如下:
参数
描述
left
参与合并到左侧DataFrame
right
参与合并到右侧DataFrame
how
合并方式(‘inner’、‘outer’、‘left’、‘right’)其中之一,默认为‘inner’
on
用于连接的列名。未指定则使用两列的交集作为连接键
left_on
左侧DataFrame中用作连接键的列
right_on
右侧DataFrame中用作连接键的列
left_index
将左侧的行索引用作连接键
right_index
将右侧的行索引用作连接键
sort
对合并后的数据进行排序,默认为True
suffixes
用于追加到重叠列名的末尾。例如,左右两个DataFrame都有‘data’列,则结果中就会出现‘data_x’和‘data_y’
copy
默认总是复制
以一个例子开始:
>>>import numpy as np
>>>import pandas as pd
>>>df1 = pd.DataFrame({'data1': np.arange(7), 'name': list('bbbaacd')})
>>>df1
data1 name
0 0 b
1 1 b
2 2 b
3 3 a
4 4 a
5 5 c
6 6 d
>>>df2 = pd.DataFrame({'data2': [0, 2, 4], 'name': ['a', 'b', 'c']})
>>>df2
data2 name
0 0 a
1 2 b
2 4 c
>>>pd.merge(df1, df2)
data1 name data2
0 0 b 2
1 1 b 2
2 2 b 2
3 3 a 0
4 4 a 0
5 5 c 4
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
>>>importnumpyasnp
>>>importpandasaspd
>>>df1=pd.DataFrame({'data1':np.arange(7),'name':list('bbbaacd')})
>>>df1
data1name
00b
11b
22b
33a
44a
55c
66d
>>>df2=pd.DataFrame({'data2':[0,2,4],'name':['a','b','c']})
>>>df2
data2name
00a
12b
24c
>>>pd.merge(df1,df2)
data1namedata2
00b2
11b2
22b2
33a0
44a0
55c4
在这个例子中,默认使用两个DataFrame的交集作为合并键,也就是'name'列。这是多对一的合并,也就是说df1中有多个重复值与df2中一个值合并(2个’a’对一个’a’,3个’b’对一个’b’)。默认是'inner'的方式,只要两者都有的值才合并(’a’, ‘b’, ‘c’),还可以使用其他的合并方式:
# 并集合并
>>>pd.merge(df1, df2, how='outer')
data1 name data2
0 0 b 2.0
1 1 b 2.0
2 2 b 2.0
3 3 a 0.0
4 4 a 0.0
5 5 c 4.0
6 6 d NaN
# 左合并
>>>pd.merge(df1, df2, how='left')
data1 name data2
0 0 b 2.0
1 1 b 2.0
2 2 b 2.0
3 3 a 0.0
4 4 a 0.0
5 5 c 4.0
6 6 d NaN
# 右合并
>>>pd.merge(df1, df2, how='right')
data1 name data2
0 0 b 2
1 1 b 2
2 2 b 2
3 3 a 0
4 4 a 0
5 5 c 4
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# 并集合并
>>>pd.merge(df1,df2,how='outer')
data1namedata2
00b2.0
11b2.0
22b2.0
33a0.0
44a0.0
55c4.0
66dNaN
# 左合并
>>>pd.merge(df1,df2,how='left')
data1namedata2
00b2.0
11b2.0
22b2.0
33a0.0
44a0.0
55c4.0
66dNaN
# 右合并
>>>pd.merge(df1,df2,how='right')
data1namedata2
00b2
11b2
22b2
33a0
44a0
55c4
可以根据想要的合并方式选择参数;如何合并的列名不一样,此时就要通过指定列名进行合并:
>>>df1 = pd.DataFrame({'data1': np.arange(7), 'name1': list('bbbaacd')})
>>>df1
data1 name1
0 0 b
1 1 b
2 2 b
3 3 a
4 4 a
5 5 c
6 6 d
>>>df2 = pd.DataFrame({'data2': [0, 2, 4], 'name2': ['a', 'b', 'c']})
>>>df2
data2 name2
0 0 a
1 2 b
2 4 c
>>>pd.merge(df1, df2, left_on='name1', right_on='name2')
data1 name1 data2 name2
0 0 b 2 b
1 1 b 2 b
2 2 b 2 b
3 3 a 0 a
4 4 a 0 a
5 5 c 4 c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
>>>df1=pd.DataFrame({'data1':np.arange(7),'name1':list('bbbaacd')})
>>>df1
data1name1
00b
11b
22b
33a
44a
55c
66d
>>>df2=pd.DataFrame({'data2':[0,2,4],'name2':['a','b','c']})
>>>df2
data2name2
00a
12b
24c
>>>pd.merge(df1,df2,left_on='name1',right_on='name2')
data1name1data2name2
00b2b
11b2b
22b2b
33a0a
44a0a
55c4c
可以看出,默认也是交集合并,通过left_on和right_on指定了需要合并的列,得到合并后的结果。除了多对一的合并,还有多对多的合并,例如:
>>>df1 = pd.DataFrame({'data1': np.arange(7), 'name': list('bbbaacd')})
>>>df1
data1 name
0 0 b
1 1 b
2 2 b
3 3 a
4 4 a
5 5 c
6 6 d
>>>df2 = pd.DataFrame({'data2': np.arange(4), 'name': list('aabc')})
>>>df2
data2 name
0 0 a
1 1 a
2 2 b
3 3 c
>>>pd.merge(df1, df2, on='name', how='outer')
data1 name data2
0 0 b 2.0
1 1 b 2.0
2 2 b 2.0
3 3 a 0.0
4 3 a 1.0
5 4 a 0.0
6 4 a 1.0
7 5 c 3.0
8 6 d NaN
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
>>>df1=pd.DataFrame({'data1':np.arange(7),'name':list('bbbaacd')})
>>>df1
data1name
00b
11b
22b
33a
44a
55c
66d
>>>df2=pd.DataFrame({'data2':np.arange(4),'name':list('aabc')})
>>>df2
data2name
00a
11a
22b
33c
>>>pd.merge(df1,df2,on='name',how='outer')
data1namedata2
00b2.0
11b2.0
22b2.0
33a0.0
43a1.0
54a0.0
64a1.0
75c3.0
86dNaN
多对多合并的原则是:df1中有两个’a’行,df2中有两个’a’行,因此总共就有四个’a’行,是两者数量相乘。还可以根据多个列进行合并:
>>>df1 = pd.DataFrame({'data1': range(3), 'name1': list('aab'), 'name2': ['one', 'one', 'two']})
>>>df1
data1 name1 name2
0 0 a one
1 1 a one
2 2 b two
>>>df2 = pd.DataFrame({'data2': range(3), 'name1': list('aab'), 'name2': ['one', 'two', 'one']})
>>>df2
data2 name1 name2
0 0 a one
1 1 a two
2 2 b one
>>>pd.merge(df1, df2, on=['name1', 'name2'], how='outer')
data1 name1 name2 data2
0 0.0 a one 0.0
1 1.0 a one 0.0
2 2.0 b two NaN
3 NaN a two 1.0
4 NaN b one 2.0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
>>>df1=pd.DataFrame({'data1':range(3),'name1':list('aab'),'name2':['one','one','two']})
>>>df1
data1name1name2
00aone
11aone
22btwo
>>>df2=pd.DataFrame({'data2':range(3),'name1':list('aab'),'name2':['one','two','one']})
>>>df2
data2name1name2
00aone
11atwo
22bone
>>>pd.merge(df1,df2,on=['name1','name2'],how='outer')
data1name1name2data2
00.0aone0.0
11.0aone0.0
22.0btwoNaN
3NaNatwo1.0
4NaNbone2.0
在这里两个键形成一个组合,df1中有两个(a, one),而df2中只有一个(a, one),因此相乘就是两个。
merge()函数使用起来是十分灵活的,不仅可以根据列合并,而且还能将索引-索引合并,索引-列合并,只需要指定相应的参数即可:
>>>df1
data1 name1 name2
0 0 a one
1 1 a one
2 2 b two
>>>df2
data2 name1 name2
0 0 a one
1 1 a two
2 2 b one
# 索引-索引合并
>>>pd.merge(df1, df2, left_index=True, right_index=True)
data1 name1_x name2_x data2 name1_y name2_y
0 0 a one 0 a one
1 1 a one 1 a two
2 2 b two 2 b one
>>>df3 = pd.DataFrame({'data3': range(3)}, index=list('abc'))
>>>df3
data3
a 0
b 1
c 2
>>>pd.merge(df1, df3, left_on='name1', right_index=True, how='outer')
data1 name1 name2 data3
0 0.0 a one 0
1 1.0 a one 0
2 2.0 b two 1
2 NaN c NaN 2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
>>>df1
data1name1name2
00aone
11aone
22btwo
>>>df2
data2name1name2
00aone
11atwo
22bone
# 索引-索引合并
>>>pd.merge(df1,df2,left_index=True,right_index=True)
data1name1_xname2_xdata2name1_yname2_y
00aone0aone
11aone1atwo
22btwo2bone
>>>df3=pd.DataFrame({'data3':range(3)},index=list('abc'))
>>>df3
data3
a0
b1
c2
>>>pd.merge(df1,df3,left_on='name1',right_index=True,how='outer')
data1name1name2data3
00.0aone0
11.0aone0
22.0btwo1
2NaNcNaN2
参见最开始的merge()函数的参数设定,通过调控参数能够实现非常灵活的合并操作。
concat()函数
该函数能够实现轴向数据集的连接,同样它的参数有:
参数
描述
objs
参与连接的对象,必需参数
axis
指定轴,默认为0
join
‘inner’或者‘outer’,默认为‘outer’,指明其他轴的索引按哪种方式进行合并
join_axes
指明用于其他n-1条轴的索引,不执行并集/交集运算
keys
与连接对象有关的值,用于形成连接轴向上的层次化索引。可以是任意值的列表或数组
levels
指定用作层次化索引各级别上的索引
names
用于创建分层级别的名称,如果设置了keys和levels
verify_integrity
检查结果对象新轴上的重复情况,如果发现则引发异常。默认False允许重复
ignore_index
不保留连接轴上的索引,产生一组新索引
例如:
>>>a1 = pd.Series([0, 1])
>>>a2 = pd.Series([2, 3, 4])
>>>a3 = pd.Series([5, 6])
>>>a = pd.concat([a1, a2, a3])
>>>a
0 0
1 1
0 2
1 3
2 4
0 5
1 6
dtype: int64
>>>pd.concat([a1, a2, a3], ignore_index=True)
0 0
1 1
2 2
3 3
4 4
5 5
6 6
dtype: int64
# 或者
>>>a.set_axis(range(7), inplace=True)
>>>a
0 0
1 1
2 2
3 3
4 4
5 5
6 6
dtype: int64
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
>>>a1=pd.Series([0,1])
>>>a2=pd.Series([2,3,4])
>>>a3=pd.Series([5,6])
>>>a=pd.concat([a1,a2,a3])
>>>a
00
11
02
13
24
05
16
dtype:int64
>>>pd.concat([a1,a2,a3],ignore_index=True)
00
11
22
33
44
55
66
dtype:int64
# 或者
>>>a.set_axis(range(7),inplace=True)
>>>a
00
11
22
33
44
55
66
dtype:int64
将三个Series的值和索引连接起来,使用ignore_index=True能够忽略索引值,或者使用set_axis函数可以重新修改索引。
默认是在axis=0上连接,我们也可以指定方向:
>>>pd.concat([a1, a2, a3], axis=1)
0 1 2
0 0.0 2 5.0
1 1.0 3 6.0
2 NaN 4 NaN
1
2
3
4
5
>>>pd.concat([a1,a2,a3],axis=1)
012
00.025.0
11.036.0
2NaN4NaN
此时是在索引的并集上进行连接,可以使用join参数改变连接方式:
>>>pd.concat([a1, a2, a3], axis=1, join='inner')
0 1 2
0 0 2 5
1 1 3 6
1
2
3
4
>>>pd.concat([a1,a2,a3],axis=1,join='inner')
012
0025
1136
可以通过join_axes指定在其他轴上使用的索引:
>>>pd.concat([a1, a3], axis=1, join_axes=[[0, 2, 1]])
0 1
0 0.0 5.0
2 NaN NaN
1 1.0 6.0
1
2
3
4
5
>>>pd.concat([a1,a3],axis=1,join_axes=[[0,2,1]])
01
00.05.0
2NaNNaN
11.06.0
可以通过keys参数创建一个层次化索引:
>>>pd.concat([a1, a2, a3], keys=['one' , 'two', 'three'])
one 0 0
1 1
two 0 2
1 3
2 4
three 0 5
1 6
dtype: int64
>>>pd.concat([a1, a2, a3], axis=1, keys=['one', 'two', 'three'])
one two three
0 0.0 2 5.0
1 1.0 3 6.0
2 NaN 4 NaN
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
>>>pd.concat([a1,a2,a3],keys=['one','two','three'])
one00
11
two02
13
24
three05
16
dtype:int64
>>>pd.concat([a1,a2,a3],axis=1,keys=['one','two','three'])
onetwothree
00.025.0
11.036.0
2NaN4NaN
对DataFrame的操作也是一样的:
>>>df1
data1 name1 name2
0 0 a one
1 1 a one
2 2 b two
>>>df2
data2 name1 name2
0 0 a one
1 1 a two
2 2 b one
>>>pd.concat([df1, df2], axis=1, keys=['one', 'two'])
one two
data1 name1 name2 data2 name1 name2
0 0 a one 0 a one
1 1 a one 1 a two
2 2 b two 2 b one
# 或者
>>>pd.concat({'one': df1, 'two': df2}, axis=1)
one two
data1 name1 name2 data2 name1 name2
0 0 a one 0 a one
1 1 a one 1 a two
2 2 b two 2 b one
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
>>>df1
data1name1name2
00aone
11aone
22btwo
>>>df2
data2name1name2
00aone
11atwo
22bone
>>>pd.concat([df1,df2],axis=1,keys=['one','two'])
onetwo
data1name1name2data2name1name2
00aone0aone
11aone1atwo
22btwo2bone
# 或者
>>>pd.concat({'one':df1,'two':df2},axis=1)
onetwo
data1name1name2data2name1name2
00aone0aone
11aone1atwo
22btwo2bone
可以看出在DataFrame上有两种方法构建层次化索引,要么使用keys参数,要么构建一个字典,字典的键会作为keys的值。
使用names参数可以管理层次化索引:
>>>pd.concat([df1, df2], axis=1, keys=['one', 'two'], names=['fist_layer', 'second_layer'])
fist_layer one two
second_layer data1 name1 name2 data2 name1 name2
0 0 a one 0 a one
1 1 a one 1 a two
2 2 b two 2 b one
1
2
3
4
5
6
>>>pd.concat([df1,df2],axis=1,keys=['one','two'],names=['fist_layer','second_layer'])
fist_layeronetwo
second_layerdata1name1name2data2name1name2
00aone0aone
11aone1atwo
22btwo2bone
总结
pandas提供的合并操作非常简单和实用,功能都是从实际需求中出发, 让我们能够更加高效地处理数据。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。