2 联合与合并数据集
包含在pandas 对象的数据可以通过多种方式联合在一起:
- pandas.merge 根据一个或多个键将行进行链接。
- pandas.concat 使对象在轴向上进行粘合或堆叠
- combine_first 实例方法允许将重叠的数据拼接在一起,以使用一个对象中的值填充另一个对象中的缺失值
2.1 数据库风格的 dataframe 连接
df1=pd.DataFrame({'key':['b','b','a','c','a','a','b'],'data1':range(7)})
df2=pd.DataFrame({'key':['a','b','d'],'data2':range(3)})
df1
key data1
0 b 0
1 b 1
2 a 2
3 c 3
4 a 4
5 a 5
6 b 6
df2
key data2
0 a 0
1 b 1
2 d 2
pd.merge(df1,df2) # 多对一链接的例子,df1 的 key 列有多个a b ,df2 每个值仅有一行。
key data1 data2
0 b 0 1
1 b 1 1
2 b 6 1 # 这里没有指定在哪一列进行链接,自动将重叠列名作为链接的键
3 a 2 0
4 a 4 0
5 a 5 0
pd.merge(df1,df2,on='key') # 这是显示的指定链接的键
df3=pd.DataFrame({'lkey':['b','b','a','c','a','a','b'],'data1':range(7)})
df4=pd.DataFrame({'rkey':['a','b','d'],'data2':range(3)})
pd.merge(df3,df4,left_on='lkey',right_on='rkey') # 如果每个对象的列名是不同的,你可以分别为他们指定列名
lkey data1 rkey data2
0 b 0 b 1
1 b 1 b 1
2 b 6 b 1
3 a 2 a 0
4 a 4 a 0
5 a 5 a 0
可以看到,结果中缺少了 ‘c’ 和 ‘d’ 的值以及相关数据。默认情况下,merge 做的是内连接(inner join),结果中的键是两张表的交集。其他可选的选项有 left right outer。外连接( outer join)是键的并集,
pd.merge(df1,df2,how='outer')
key data1 data2
0 b 0.0 1.0
1 b 1.0 1.0
2 b 6.0 1.0
3 a 2.0 0.0
4 a 4.0 0.0
5 a 5.0 0.0
6 c 3.0 NaN
7 d NaN 2.0
how参数不同连接类型 | 行为 |
---|---|
inner | 只对两张表都有的键的交集进行联合。 |
left | 对所有左表的键进行联合 |
right | 对所有右表的键进行联合 |
outer | 对两张表都有的键的并集进行联合。 |
多对多的合并:
df1=pd.DataFrame({'key':['b','b','a','c','a','b'],'data1':range(6)})
df2=pd.DataFrame({'key':['a','b','a','b','d'],'data2':range(5)})
df1
key data1
0 b 0
1 b 1
2 a 2
3 c 3
4 a 4
5 b 5
df2
key data2
0 a 0
1 b 1
2 a 2
3 b 3
4 d 4
pd.merge(df1,df2,on='key',how='left')
key data1 data2
0 b 0 1.0
1 b 0 3.0
2 b 1 1.0
3 b 1 3.0
4 a 2 0.0
5 a 2 2.0
6 c 3 NaN
7 a 4 0.0
8 a 4 2.0
9 b 5 1.0
10 b 5 3.0
多对多连接是行的笛卡尔积,就是A={a,b}, B={0,1,2},则A×B={(a, 0), (a, 1), (a, 2), (b, 0), (b, 1), (b, 2)}
上面这个以df1 为准来连接,df1 中 b=[0,1,5] a=[2,4] c=3 ,df2 中 b=[1,3] a=[0,2] 。按笛卡尔积来算的话,连接后的 b 应该有6个,[(0,1),(0,3),(1,1),(1,3),(5,1),(5,3)] 对照上面确实是,按照 df1 的索引排列。连接方法仅影响结果中显示的不同键值
pd.merge(df1,df2,how='inner')
key data1 data2
0 b 0 1
1 b 0 3
2 b 1 1
3 b 1 3 # 两个键的交集。
4 b 5 1
5 b 5 3
6 a 2 0
7 a 2 2
8 a 4 0
9 a 4 2
left = pd.DataFrame({'key1': ['foo', 'foo', 'bar'],
'key2': ['one', 'two', 'one'],
'lval': [1, 2, 3]})
right = pd.DataFrame({'key1': ['foo', 'foo', 'bar', 'bar'],
'key2': ['one', 'one', 'one', 'two'],
'rval': [4, 5, 6, 7]})
pd.merge(left, right, on=['key1', 'key2'], how='outer')
key1 key2 lval rval
0 foo one 1.0 4.0 # 使用多个键进行合并,传入一个列名的列表。
1 foo one 1.0 5.0
2 foo two 2.0 NaN
3 bar one 3.0 6.0
4 bar two NaN 7.0
# 合并操作最后的问题是如何处理重叠的列名,虽然可以通过 rname 的方式重命名轴标签,
# 但是 merge 的suffixes 后缀选项用于在左右两边dataframe 对象的重叠列名后指定需要添加的字符串
pd.merge(left,right,on='key1')
key1 key2_x lval key2_y rval
0 foo one 1 one 4
1 foo one 1 one 5
2 foo two 2 one 4
3 foo two 2 one 5
4 bar one 3 one 6
5 bar one 3 two 7
pd.merge(left,right,on='key1',suffixes=('_left','_right'))
key1 key2_left lval key2_right rval
0 foo one 1 one 4
1 foo one 1 one 5
2 foo two 2 one 4
3 foo two 2 one 5
4 bar one 3 one 6
5 bar one 3 two 7
2.2 根据索引合并
某些情况下,dataframe 中用于合并的键是他的索引。在这种情况下,可以传递 left_index=True or right_index=True 来表示索引需要用来作为合并的键。
left1 = pd.DataFrame({'key': ['a', 'b', 'a', 'a', 'b', 'c'],
'value': range(6)})
right1 = pd.DataFrame({'group_val': [3.5, 7]}, index=['a', 'b'])
left1
key value
0 a 0
1 b 1
2 a 2
3 a 3
4 b 4
5 c 5
right1
group_val
a 3.5
b 7.0
pd.merge(left1, right1, left_on='key', right_index=True) # 就是将右边的索引当键了
key value group_val
0 a 0 3.5
2 a 2 3.5
3 a 3 3.5
1 b 1 7.0
4 b 4 7.0
lefth = pd.DataFrame({'key1': ['Ohio', 'Ohio', 'Ohio',
'Nevada', 'Nevada'],
'key2': [2000, 2001, 2002, 2001, 2002],
'data': np.arange(5.)})
righth = pd.DataFrame(np.arange(12).reshape((6, 2)),
index=[['Nevada', 'Nevada', 'Ohio', 'Ohio',
'Ohio', 'Ohio'],
[2001, 2000, 2000, 2000, 2001, 2002]],
columns=['event1', 'event2'])
lefth
key1 key2 data
0 Ohio 2000 0.0
1 Ohio 2001 1.0
2 Ohio 2002 2.0
3 Nevada 2001 3.0
4 Nevada 2002 4.0
righth
event1 event2
Nevada 2001 0 1
2000 2 3
Ohio 2000 4 5
2000 6 7
2001 8 9
2002 10 11
pd.merge(lefth,righth,left_on=['key1','key2'],right_index=True) # 在多层索引的情况下,索引上连接是一个隐式的多键合并
key1 key2 data event1 event2 # 这种情况下,必须以列表的方式指名合并所需多个列
0 Ohio 2000 0.0 4 5
0 Ohio 2000 0.0 6 7
1 Ohio 2001 1.0 8 9
2 Ohio 2002 2.0 10 11 # 耐心看看还是能看懂的,
3 Nevada 2001 3.0 0 1
left2 = pd.DataFrame([[1., 2.], [3., 4.], [5., 6.]],
index=['a', 'c', 'e'],
columns=['Ohio', 'Nevada'])
right2 = pd.DataFrame([[7., 8.], [9., 10.], [11., 12.], [13, 14]],
index=['b', 'c', 'd', 'e'],
columns=['Missouri', 'Alabama'])
left2
Ohio Nevada
a 1.0 2.0
c 3.0 4.0
e 5.0 6.0
right2
Missouri Alabama
b 7.0 8.0
c 9.0 10.0
d 11.0 12.0
e 13.0 14.0
pd.merge(left2, right2, how='outer', left_index=True, right_index=True) # 使用两边的索引
Ohio Nevada Missouri Alabama
a 1.0 2.0 NaN NaN
b NaN NaN 7.0 8.0
c 3.0 4.0 9.0 10.0
d NaN NaN 11.0 12.0
e 5.0 6.0 13.0 14.0
dataframe 有一个方便的 join 方法, 用于按照索引合并,该方法也可以用于合并多个索引相同后相似但没有重叠列的 dataframe 对象。
left2.join(right2, how='outer') # 上面那个我们也可以这么写。
Ohio Nevada Missouri Alabama
a 1.0 2.0 NaN NaN
b NaN NaN 7.0 8.0
c 3.0 4.0 9.0 10.0
d NaN NaN 11.0 12.0
e 5.0 6.0 13.0 14.0
left1.join(right1, on='key') # join 方法进行连接键上的左连接,完全保留左边 dataframe 的行索引。
key value group_val
0 a 0 3.5
1 b 1 7.0
2 a 2 3.5
3 a 3 3.5
4 b 4 7.0
5 c 5 NaN
another = pd.DataFrame([[7., 8.], [9., 10.], [11., 12.], [16., 17.]],
index=['a', 'c', 'e', 'f'],
columns=['New York', 'Oregon'])
another
New York Oregon
a 7.0 8.0
c 9.0 10.0
e 11.0 12.0
f 16.0 17.0 # 对于一些简单索引-索引合并,可以向join 方法传入一个dataframe 列表,这个方法可以替代更为通用的concat 函数
left2.join([right2,another],how='outer')
Ohio Nevada Missouri Alabama New York Oregon # 就是多加一些合并的数据吧。。。
a 1.0 2.0 NaN NaN 7.0 8.0
c 3.0 4.0 9.0 10.0 9.0 10.0
e 5.0 6.0 13.0 14.0 11.0 12.0
b NaN NaN 7.0 8.0 NaN NaN
d NaN NaN 11.0 12.0 NaN NaN
f NaN NaN NaN NaN 16.0 17.0
好难啊,感觉整个人都傻了。。。。。。