8.2 Combining and Merging Datasets(合并数据集)
pandas
里有几种方法可以合并数据:
pandas.merge
按一个或多个key
把DataFrame
中的行连接起来。这个和SQL
或其他一些关系型数据库中的join
操作相似。
pandas.concat
在一个axis
(轴)上,串联或堆叠(stack
)多个对象。
combine_first
实例方法(instance method
)能拼接相互之间有重复的数据,并用一个对象里的值填满缺失值
这里每一个都会给出一些例子。这些用法贯穿这本书。
1 Database-Style DataFrame Joins(数据库风格的DataFrame Joins)
Merge
或join
操作,能通过一个或多个key
,把不同的数据集的行连接在一起。这种操作主要集中于关系型数据库。pandas
中的merge
函数是这种操作的主要切入点:
import pandas as pd
import numpy as np
df1 = pd.DataFrame({'key': ['b', 'b', 'a', 'c', 'a', 'a', 'b'],
'data1': range(7)})
df1
|
data1 |
key |
0 |
0 |
b |
1 |
1 |
b |
2 |
2 |
a |
3 |
3 |
c |
4 |
4 |
a |
5 |
5 |
a |
6 |
6 |
b |
df2 = pd.DataFrame({'key': ['a', 'b', 'd'],
'data2': range(3)})
df2
|
data2 |
key |
0 |
0 |
a |
1 |
1 |
b |
2 |
2 |
d |
这个例子是many-to-one join
(多个变为一个的结合);在df1
中有标签为a
和b
的行,而df2
中的key
列,每一行只有对应的一个值。调用merge
我们可以得到:
pd.merge(df1, df2)
|
data1 |
key |
data2 |
0 |
0 |
b |
1 |
1 |
1 |
b |
1 |
2 |
6 |
b |
1 |
3 |
2 |
a |
0 |
4 |
4 |
a |
0 |
5 |
5 |
a |
0 |
这里我们并没有指定按哪一列来合并。如果我们没有指定,merge
会用两个对象中都存在的列名作为key
(键)。当然,最好还是清楚指定比较好:
pd.merge(df1, df2, on='key')
|
data1 |
key |
data2 |
0 |
0 |
b |
1 |
1 |
1 |
b |
1 |
2 |
6 |
b |
1 |
3 |
2 |
a |
0 |
4 |
4 |
a |
0 |
5 |
5 |
a |
0 |
如果每一个对象中的列名不一会,我们可以分别指定:
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')
|
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 join
(内联结),结果中的key
是交集的结果,或者在两个表格中都有的集合。其他一些可选项,比如left, right, outer。outer join
(外联结)取key
的合集,其实就是left join
和right join
同时应用的效果:
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 |
many-to-many
(多对多)结合也被定义好了,不过可能不是那么直观。这里有一个例子:
df1 = pd.DataFrame({'key': ['b', 'b', 'a', 'c', 'a', 'b'],
'data1': range(6)})
df1
|
data1 |
key |
0 |
0 |
b |
1 |
1 |
b |
2 |
2 |
a |
3 |
3 |
c |
4 |
4 |
a |
5 |
5 |
b |
df2 = pd.DataFrame({'key': ['a', 'b', 'a', 'b', 'd'],
'data2': range(5)})
df2
|
data2 |
key |
0 |
0 |
a |
1 |
1 |
b |
2 |
2 |
a |
3 |
3 |
b |
4 |
4 |
d |
pd.merge(df1, df2, on='key', how='left')
|
data1 |
key |
data2 |
0 |
0 |
b |
1.0 |
1 |
0 |
b |
3.0 |
2 |
1 |
b |
1.0 |
3 |
1 |
b |
3.0 |
4 |
2 |
a |
0.0 |
5 |
2 |
a |
2.0 |
6 |
3 |
c |
NaN |
7 |
4 |
a |
0.0 |
8 |
4 |
a |
2.0 |
9 |
5 |
b |
1.0 |
10 |
5 |
b |
3.0 |
many-to-many join
是对行进行笛卡尔集运算。(两个集合X和Y的笛卡儿积(Cartesian product
),又称直积,在集合论中表示为X × Y,是所有可能的有序对组成的集合。比如1到13是一个集合,四种花色是一个集合,二者的笛卡尔积就有52个元素)。这里在左侧的DataFrame
中有三行含b,右边的DataFrame
则有两行含b,于是结果是有六行含b。这个join
方法只会让不相同的key
值出现在最后的结果里:
pd.merge(df1, df2, how='inner')
|
data1 |
key |
data2 |
0 |
0 |
b |
1 |
1 |
0 |
b |
3 |
2 |
1 |
b |
1 |
3 |
1 |
b |
3 |
4 |
5 |
b |
1 |
5 |
5 |
b |
3 |
6 |
2 |
a |
0 |
7 |
2 |
a |
2 |
8 |
4 |
a |
0 |
9 |
4 |
a |
2 |
用多个key
来联结的话,用一个含有多个列名的list
来指定:
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 |
哪一种key
组合会出现在结果里取决于merge
方法的选择,可以把多个key
当做一个tuple
组成的单一key
(尽管实际上并不是这样)。
注意:当我们讲列和列进行联结时,DataFrame
中的index
对象会被丢弃。
最后一个问题是在做merge
操作的时候,如何处理重叠的列名。当我们想要手动去解决重叠问题时(参考重命名axis labels
的部分),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 Merging on Index(在index上做合并)
在一些情况下,用于合并的key
(键),可能是DataFrame
中的index
。这种情况下,可以使用left_index=True
或 right_index=True
来指明,哪一个index
被用来作为合并键:
left1 = pd.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 = pd.DataFrame({'group_val': [3.5, 7]}, index=['a', 'b'])
right1
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
的默认方法是用key
的交集,我们也可以设定用合集,即outer join
:
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 |
对于那些有多层级索引的数据,就更复杂了。index
上的merge
默认会是multiple-key merge
(复数键合并):
lefth = pd.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 = pd.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 |
在这个例子里,我们必须指明将多列合并作为一个list
(注意处理重复index
的方法是令how='outer'
):
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')
|
data |
key1 |
key2 |
event1 |
event2 |
0 |
0.0 |
Ohio |
2000.0 |
4.0 |
5.0 |
0 |
0.0 |
Ohio |
2000.0 |
6.0 |
7.0 |
1 |
1.0 |
Ohio |
2001.0 |
8.0 |
9.0 |
2 |
2.0 |
Ohio |
2002.0 |
10.0 |
11.0 |
3 |
3.0 |
Nevada |
2001.0 |
0.0 |
1.0 |
4 |
4.0 |
Nevada |
2002.0 |
NaN |
NaN |
4 |
NaN |
Nevada |
2000.0 |
2.0 |
3.0 |
同时使用两个对象里的index
来合并也是可能的:
left2 = pd.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 = pd.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)
|
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
实例,可以直接用index
来合并。这个也可以用于与其他DataFrame
进行合并,要有一样的index
但不能由重叠的列:
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 |
由于一些历史原因,在早期的pandas
版本中,DataFrame
的join
方法是在结合键上做left join
(左联结),这样会保留左侧Dataframe
的行索引。这也支持把传入的dataframe
的index
与被调用的DataFrame
的column
联结在一起:
left1.join(right1, on='key')
|
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 |
最后,对于简单的index-on-index
合并,可以直接给join
传入一个DataFrame
。(作为备选,也可以使用最普遍的concat
函数,这个在下一节会做介绍):
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 |
left2.join([right2, another])
|
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 |
left2.join([right2, another], how='outer')
|
Ohio |
Nevada |
Missouri |
Alabama |
New York |
Oregon |
a |
1.0 |
2.0 |
NaN |
NaN |
7.0 |
8.0 |
b |
NaN |
NaN |
7.0 |
8.0 |
NaN |
NaN |
c |
3.0 |
4.0 |
9.0 |
10.0 |
9.0 |
10.0 |
d |
NaN |
NaN |
11.0 |
12.0 |
NaN |
NaN |
e |
5.0 |
6.0 |
13.0 |
14.0 |
11.0 |
12.0 |
f |
NaN |
NaN |
NaN |
NaN |
16.0 |
17.0 |
2 Concatenating Along an Axis(沿着轴连接)
另一种结合方式被称为可互换的,比如concatenation, binding, or stacking
(连接,绑定,堆叠)。Numpy
中的concatenate
函数可以作用于numpy
数组:
arr = np.arange(12.).reshape((3, 4))
arr
array([[ 0., 1., 2., 3.],
[ 4., 5., 6., 7.],
[ 8., 9., 10., 11.]])
np.concatenate([arr, arr], axis=1)
array([[ 0., 1., 2., 3., 0., 1., 2., 3.],
[ 4., 5., 6., 7., 4., 5., 6., 7.],
[ 8., 9., 10., 11., 8., 9., 10., 11.]])
而在pandas
的对象中,比如Series
和DataFrame,labeled axes
(便签化的轴)能让我们做更泛化的数组连接操作。不过我们可能会有下面一些疑问:
-
如果一个对象在其他轴上的index
不同,我们应不应该在这些轴上把不同的元素连接起来,或者只用交集?
-
经过连接操作后,连接的部分在输出对象里应不应该是可被识别的?
-
concatenation axis
(连接轴)含有的数据需要被保留吗?在很多情况下,DataFrame
中一些用整数做的label
(标签)其实最好在连接后被删除。
pandas
中的concat
函数能解决上面这些问题。这里会给出几个例子来说明。假设我们有三个Series
,他们指明没有index overlap
(索引重叠):
s1 = pd.Series([0, 1], index=['a', 'b'])
s2 = pd.Series([2, 3, 4], index=['c', 'd', 'e'])
s3 = pd.Series([5, 6], index=['f', 'g'])
调用concat
,把上面的series
放在一个list
里,结果会把值和索引都整合在一起:
pd.concat([s1, s2, s3])
a 0
b 1
c 2
d 3
e 4
f 5
g 6
dtype: int64
默认情况下,concat
中axis=0
,结果会得到一个新的而series
。如果令axis=1
, 结果会变成一个DataFrame
(axis=1
是列):
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 |
这种情况下,不会与其他轴产生重叠,效果与join
中的outer join
一样。你也可以通过设定join='inner'
来使用交集:
s4 = pd.concat([s1, s3])
s4
a 0
b 1
f 5
g 6
dtype: int64
pd.concat([s1, s4], axis=1)
|
0 |
1 |
a |
0.0 |
0 |
b |
1.0 |
1 |
f |
NaN |
5 |
g |
NaN |
6 |
pd.concat([s1, s4], axis=1, join='inner')
因为join='inner'
,所以f和g标签消失了。
你也可以在join_axes
中指定使用哪些轴:
pd.concat([s1, s4], axis=1, join_axes=[['a', 'c', 'b', 'e']])
|
0 |
1 |
a |
0.0 |
0.0 |
c |
NaN |
NaN |
b |
1.0 |
1.0 |
e |
NaN |
NaN |
一个潜在的问题是连接的部分在结果里是不可辨识的。假设我们想在连接轴上创建一个多层级索引,我们需要用到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
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
,那么keys
会变为DataFrame
的column header
(列头):
print(s1)
print(s2)
print(s3)
a 0
b 1
dtype: int64
c 2
d 3
e 4
dtype: int64
f 5
g 6
dtype: int64
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对象上:
df1 = pd.DataFrame(np.arange(6).reshape(3, 2), index=['a', 'b', 'c'],
columns=['one', 'two'])
df1
|
one |
two |
a |
0 |
1 |
b |
2 |
3 |
c |
4 |
5 |
df2 = pd.DataFrame(5 + np.arange(4).reshape(2, 2), index=['a', 'c'],
columns=['three', 'four'])
df2
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 |
如果导入一个dict
而不是list
,那么dict
的key
会被用于上面concat
中的keys
选项:
pd.concat({'level1': df1, 'level2': df2}, axis=1)
|
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 |
还有其他一些选项负责多层级索引的设定(表8-3)。比如,可以给创建的axis
level
(轴层级)用names
参数来命名:
pd.concat([df1, df2], axis=1, keys=['level1', 'level2'],
names=['upper', 'lower'])
upper |
level1 |
level2 |
lower |
one |
two |
three |
four |
a |
0 |
1 |
5.0 |
6.0 |
b |
2 |
3 |
NaN |
NaN |
c |
4 |
5 |
7.0 |
8.0 |
最后我们关心的是,在DataFrame
中,行索引(row index
)没有包含相关的数据:
df1 = pd.DataFrame(np.random.randn(3, 4), columns=['a', 'b', 'c', 'd'])
df1
|
a |
b |
c |
d |
0 |
1.049308 |
-0.660746 |
1.152071 |
-1.447441 |
1 |
-0.484170 |
-0.096755 |
-0.815349 |
1.839818 |
2 |
-0.277541 |
0.164721 |
-0.012481 |
0.477152 |
df2 = pd.DataFrame(np.random.randn(2, 3), columns=['b', 'd', 'a'])
df2
|
b |
d |
a |
0 |
-0.556378 |
-2.286601 |
-0.494776 |
1 |
1.152716 |
0.270165 |
-0.222289 |
这种情况下,可以设置ignore_index=True
:
pd.concat([df1, df2], ignore_index=True)
|
a |
b |
c |
d |
0 |
1.049308 |
-0.660746 |
1.152071 |
-1.447441 |
1 |
-0.484170 |
-0.096755 |
-0.815349 |
1.839818 |
2 |
-0.277541 |
0.164721 |
-0.012481 |
0.477152 |
3 |
-0.494776 |
-0.556378 |
NaN |
-2.286601 |
4 |
-0.222289 |
1.152716 |
NaN |
0.270165 |
3 Combining Data with Overlap
另一种数据结合方法既不属于merge
,也不属于concatenation
。比如两个数据集,index
可能完全覆盖,或覆盖一部分。这里举个例子,考虑下numpy
的where
函数,可以在数组上进行类似于if-else
表达式般的判断:
a = pd.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 = pd.Series(np.arange(len(a), dtype=np.float64),
index=['f', 'e', 'd', 'c', 'b', 'a'])
b
f 0.0
e 1.0
d 2.0
c 3.0
b 4.0
a 5.0
dtype: float64
np.where(pd.isnull(a), b, a)
array([ 0. , 2.5, 2. , 3.5, 4.5, 5. ])
Series
有一个combine_first
方法,效果和上面是一样,而且还会自动对齐(比如把index
按字母进行排列):
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 = pd.DataFrame({'a': [1., np.nan, 5., np.nan],
'b': [np.nan, 2., np.nan, 6.],
'c': range(2, 18, 4)})
df1
|
a |
b |
c |
0 |
1.0 |
NaN |
2 |
1 |
NaN |
2.0 |
6 |
2 |
5.0 |
NaN |
10 |
3 |
NaN |
6.0 |
14 |
df2 = pd.DataFrame({'a': [5., 4., np.nan, 3., 7.],
'b': [np.nan, 3., 4., 6., 8.]})
df2
|
a |
b |
0 |
5.0 |
NaN |
1 |
4.0 |
3.0 |
2 |
NaN |
4.0 |
3 |
3.0 |
6.0 |
4 |
7.0 |
8.0 |
df1.combine_first(df2)
|
a |
b |
c |
0 |
1.0 |
NaN |
2.0 |
1 |
4.0 |
2.0 |
6.0 |
2 |
5.0 |
4.0 |
10.0 |
3 |
3.0 |
6.0 |
14.0 |
4 |
7.0 |
8.0 |
NaN |