我正在尝试合并两个数据帧,并用右df替换左df中的nan,我可以用以下三行代码来做到这一点,但是我想知道是否有更好/更短的方法? / p>
# Example data (my actual df is ~500k rows x 11 cols)
df1 = pd.DataFrame({'a': [1,2,3,4], 'b': [0,1,np.nan, 1], 'e': ['a', 1, 2,'b']})
df2 = pd.DataFrame({'a': [1,2,3,4], 'b': [np.nan, 1, 0, 1]})
# Merge the dataframes...
df = df1.merge(df2, on='a', how='left')
# Fillna in 'b' column of left df with right df...
df['b'] = df['b_x'].fillna(df['b_y'])
# Drop the columns no longer needed
df = df.drop(['b_x', 'b_y'], axis=1)
答案 0 :(得分:5)
简短版本
df1.b.fillna(df1.a.map(df2.set_index('a').b),inplace=True)
df1
Out[173]:
a b e
0 1 0.0 a
1 2 1.0 1
2 3 0.0 2
3 4 1.0 b
自从您提到过,将会有多列
df = df1.combine_first(df1[['a']].merge(df2, on='a', how='left'))
df
Out[184]:
a b e
0 1 0.0 a
1 2 1.0 1
2 3 0.0 2
3 4 1.0 b
我们也可以使用df传递到fillna
df1.fillna(df1[['a']].merge(df2, on='a', how='left'))
Out[185]:
a b e
0 1 0.0 a
1 2 1.0 1
2 3 0.0 2
3 4 1.0 b
答案 1 :(得分:4)
令人困惑的合并问题是,两个数据帧都有一个'b'列,但是左右版本的NaN在不匹配的位置。您想避免一开始就从merge
中获取不必要的多个“ b”列“ b_x”,“ b_y” :
merge(df2, 'left')
,这将从正确的数据帧中拾取“ b”(因为它仅存在于正确的df中)df1.update(...)
,这将用df1['b']
来更新df2的'b'列中的NaN。解决方案:
df1.update(df1[['a', 'e']].merge(df2, 'left'))
df1
a b e
0 1 0.0 a
1 2 1.0 1
2 3 0.0 2
3 4 1.0 b
注意:由于我使用了merge(..., how='left')
,因此保留了调用数据帧的行顺序。如果我的df1
的值a
不正确
a b e
0 1 0.0 a
1 2 1.0 1
2 4 1.0 b
3 3 NaN 2
结果将是
df1.update(df1[['a', 'e']].merge(df2, 'left'))
df1
a b e
0 1 0.0 a
1 2 1.0 1
2 4 1.0 b
3 3 0.0 2
符合预期。
如果您希望在涉及更多列时更加明确
df1.update(df1.drop('b', 1).merge(df2, 'left', 'a'))
如果您不想update
数据框,我们可以使用combine_first
快速
df1.combine_first(df1[['a', 'e']].merge(df2, 'left'))
明确
df1.combine_first(df1.drop('b', 1).merge(df2, 'left', 'a'))
'left'
merge
可以保留顺序,但不保留索引。这是极端保守的方法:
df3 = df1.drop('b', 1).merge(df2, 'left', on='a').set_index(df1.index)
df1.combine_first(df3)
答案 2 :(得分:2)
只有索引被指定(重要说明),我们才能使用update
:
df1['b'].update(df2['b'])
a b e
0 1 0.0 a
1 2 1.0 1
2 3 0.0 2
3 4 1.0 b
或者只是fillna
:
df1['b'].fillna(df2['b'], inplace=True)
如果您未指定索引,请参见下面的WenNYoBen's答案或comment。
答案 3 :(得分:2)
您可以屏蔽数据。
原始数据:
print(df)
one two three
0 1 1.0 1.0
1 2 NaN 2.0
2 3 3.0 NaN
print(df2)
one two three
0 4 4 4
1 4 2 4
2 4 4 3
请参见下文,根据情况填充遮罩。
# mask values where isna()
df1[['two','three']] = df1[['two','three']]\
.mask(df1[['two','three']].isna(),df2[['two','three']])
输出:
one two three
0 1 1.0 1.0
1 2 2.0 2.0
2 3 3.0 3.0