熊猫将数据框与共享列合并,左右填充

新手上路,请多包涵

我正在尝试合并两个数据帧并将左侧 df 中的 nan 替换为右侧 df,我可以用下面的三行代码来完成,但我想知道是否有更好/更短的方法?

 # 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)

原文由 Kenan 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 350
2 个回答

混淆合并的问题是 两个数据框都有一个“b”列,但左右版本在不匹配的地方有 NaN。您首先要避免从 merge 获取不需要的多个“b”列“b_x”、“b_y”

  • 从 df1 中切片非共享列 ‘a’,‘e’
  • merge(df2, 'left') ,这将从正确的数据帧中获取“b”(因为它只存在于正确的 df 中)
  • 最后做 df1.update(...) ,这将使用 df1['b'] 更新从 df2 获取的“b”列中的 NaNs

解决方案:

 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)

原文由 piRSquared 发布,翻译遵循 CC BY-SA 4.0 许可协议

简洁版本

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

原文由 BENY 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题