pandas对象中的数据可以通过一些内置的方式进行合并。
pandas.merge可以根据一个或多个键将不同DataFrame中的行连接起来。
df1 = DataFrame({'key': ['b', 'b', 'a', 'c', 'a', 'a', 'b'],
'data1': range(7)})
df2 = DataFrame({'key': ['a', 'b', 'd'],
'data2': range(3)})
pd.merge(df1, df2)
如果没有指定,merge会使用重叠列的列名作为键,但最好是显式的指定一下
pd.merge(df1, df2, on='key')
如果两个对象的列名不同,可以分别指定
df3 = DataFrame({'lkey': ['b', 'b', 'a', 'c', 'a', 'a', 'b'],
'data1': range(7)})
df4 = DataFrame({'rkey': ['a', 'b', 'd'],
'data2': range(3)})
pd.merge(df3, df4, left_on='lkey', right_on='rkey')
data1 lkey data2 rkey
0 0 b 1 b
1 1 b 1 b
2 6 b 1 b
3 2 a 0 a
4 4 a 0 a
5 5 a 0 a
可以发现,结果里面c和d以及相关的数据消失了。默认情况下,merge使用的是inner连接。
除此之外,还有left、right、outer。其中outer求取的是键的并集。
pd.merge(df1, df2, how='outer')
data1 key data2
0 0.0 b 1.0
1 1.0 b 1.0
2 6.0 b 1.0
3 2.0 a 0.0
4 4.0 a 0.0
5 5.0 a 0.0
6 3.0 c NaN
7 NaN d 2.0
如果要根据多个键进行合并,需要传入一个由列名组成的列表
left = DataFrame({'key1': ['foo', 'foo', 'bar'],
'key2': ['one', 'two', 'one'],
'lval': [1, 2, 3]})
right = 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')
对于合并运算需要考虑的问题是对重复列名的处理,merge的suffixes选项,用于指定附加到左右两个DataFrame对象的重叠列名上的字符串
pd.merge(left, right, on='key1', suffixes=('_left', '_right'))
索引上的合并
有时,DataFrame中的连接键位于索引中
left1 = DataFrame({'key': ['a', 'b', 'a', 'a', 'b', 'c'],
'value': range(6)})
left1
key value
0 a 0
1 b 1
2 a 2
3 a 3
4 b 4
5 c 5
right1 = DataFrame({'group_val': [3.5, 7]}, index=['a', 'b'])
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
由于默认的merge方法是求取连接键的交集,因此可以通过外连接的方式获得它们的并集
pd.merge(left1, right1, left_on='key', right_index=True, how='outer')
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
5 c 5 NaN
层次化索引合并
对于层次化索引,事情变得有些复杂
lefth = DataFrame({'key1': ['Ohio', 'Ohio', 'Ohio', 'Nevada', 'Nevada'],
'key2': [2000, 2001, 2002, 2001, 2002],
'data': np.arange(5.)})
lefth
data key1 key2
0 0.0 Ohio 2000
1 1.0 Ohio 2001
2 2.0 Ohio 2002
3 3.0 Nevada 2001
4 4.0 Nevada 2002
righth = DataFrame(np.arange(12).reshape((6, 2)),
index=[['Nevada', 'Nevada', 'Ohio', 'Ohio', 'Ohio', 'Ohio'],
[2001, 2000, 2000, 2000, 2001, 2002]],
columns=['event1', 'event2'])
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)
data key1 key2 event1 event2
0 0.0 Ohio 2000 4 5
0 0.0 Ohio 2000 6 7
1 1.0 Ohio 2001 8 9
2 2.0 Ohio 2002 10 11
3 3.0 Nevada 2001 0 1
合并的并集
pd.merge(lefth, righth, left_on=['key1', 'key2'],
right_index=True, how='outer')
同时使用合并双方的索引
left2 = DataFrame([[1., 2.], [3., 4.], [5., 6.]], index=['a', 'c', 'e'],
columns=['Ohio', 'Nevada'])
left2
Ohio Nevada
a 1.0 2.0
c 3.0 4.0
e 5.0 6.0
right2 = DataFrame([[7., 8.], [9., 10.], [11., 12.], [13, 14]],
index=['b', 'c', 'd', 'e'], columns=['Missouri', 'Alabama'])
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)
join实例方法
DataFrame的join实例方法能够更方便的实现按索引合并。
left2.join(right2, how='outer')
DataFrame的join方法是在连接键上做左连接
left1.join(right1, on='key')
对于简单的索引合并,join可以传入一组DataFrame
another = DataFrame([[7., 8.], [9., 10.], [11., 12.], [16., 17.]],
index=['a', 'c', 'e', 'f'], columns=['New York', 'Oregon'])
left2.join([right2, another])
left2.join([right2, another], how='outer')
轴向连接
NumPy有一个用于合并原始NumPy数组的concatenate函数
arr = np.arange(12).reshape((3, 4))
np.concatenate([arr, arr], axis=1)
Series的concat操作
假设有3个没有重叠索引的Series
s1 = Series([0, 1], index=['a', 'b'])
s2 = Series([2, 3, 4], index=['c', 'd', 'e'])
s3 = Series([5, 6], index=['f', 'g'])
将值和索引粘合在一起
pd.concat([s1, s2, s3])
默认,concat在axis=0上工作,并最终产生一个新的Series。如果传入axis=1,则结果变为一个DataFrame
pd.concat([s1, s2, s3], axis=1)
0 1 2
a 0.0 NaN NaN
b 1.0 NaN NaN
c NaN 2.0 NaN
d NaN 3.0 NaN
e NaN 4.0 NaN
f NaN NaN 5.0
g NaN NaN 6.0
获取连接的交集
s4 = pd.concat([s1 * 5, s3])
pd.concat([s1, s4], axis=1, join='inner')
通过join_axes指定在其他轴上使用的索引
pd.concat([s1, s4], axis=1, join_axes=[['a', 'c', 'b', 'e']])
如果想在连接轴上创建一个层次化索引,可以使用keys参数
result = pd.concat([s1, s1, s3], keys=['one', 'two', 'three'])
result
one a 0
b 1
two a 0
b 1
three f 5
g 6
dtype: int64
通过unstack升维
result.unstack()
a b f g
one 0.0 1.0 NaN NaN
two 0.0 1.0 NaN NaN
three NaN NaN 5.0 6.0
沿axis=1对Series进行合并,则keys成为DataFrame的列头
pd.concat([s1, s2, s3], axis=1, keys=['one', 'two', 'three'])
one two three
a 0.0 NaN NaN
b 1.0 NaN NaN
c NaN 2.0 NaN
d NaN 3.0 NaN
e NaN 4.0 NaN
f NaN NaN 5.0
g NaN NaN 6.0
DataFrame的concat操作
df1 = DataFrame(np.arange(6).reshape(3, 2), index=['a', 'b', 'c'],
columns=['one', 'two'])
df2 = DataFrame(5 + np.arange(4).reshape(2, 2), index=['a', 'c'],
columns=['three', 'four'])
pd.concat([df1, df2], axis=1, keys=['level1', 'level2'])
level1 level2
one two three four
a 0 1 5.0 6.0
b 2 3 NaN NaN
c 4 5 7.0 8.0
如果传入的不是列表是字典,则字典的键被当做keys选项的值
pd.concat({'level1': df1, 'level2': df2}, axis=1)
管理层次化创建方式的参数
pd.concat([df1, df2], axis=1, keys=['level1', 'level2'],
names=['upper', 'lower'])
忽略与数据分析无关的行索引
df1 = DataFrame(np.random.randn(3, 4), columns=['a', 'b', 'c', 'd'])
df2 = DataFrame(np.random.randn(2, 3), columns=['b', 'd', 'a'])
pd.concat([df1, df2], ignore_index=True)
合并重叠数据
假设有索引全部或部分重叠的两个数据集
a = Series([np.nan, 2.5, np.nan, 3.5, 4.5, np.nan],
index=['f', 'e', 'd', 'c', 'b', 'a'])
a
f NaN
e 2.5
d NaN
c 3.5
b 4.5
a NaN
dtype: float64
b = Series(np.arange(len(a), dtype=np.float64),
index=['f', 'e', 'd', 'c', 'b', 'a'])
b[-1] = np.nan
b
f 0.0
e 1.0
d 2.0
c 3.0
b 4.0
a NaN
dtype: float64
NumPy的where函数表达一种矢量化的if-else
np.where(pd.isnull(a), b, a)
array([ 0. , 2.5, 2. , 3.5, 4.5, nan])
Series的combine_first方法实现一样的功能,而且会进行数据对齐
b[:-2].combine_first(a[2:])
a NaN
b 4.5
c 3.0
d 2.0
e 1.0
f 0.0
dtype: float64
对于DataFrame,combine_first也会在列上做同样的事情,可以认为是用参数对象中的数据为调用者对象的确缺失数据“打补丁”
df1 = DataFrame({'a': [1., np.nan, 5., np.nan],
'b': [np.nan, 2., np.nan, 6.],
'c': range(2, 18, 4)})
df2 = DataFrame({'a': [5., 4., np.nan, 3., 7.],
'b': [np.nan, 3., 4., 6., 8.]})
df1.combine_first(df2)