kso*_*all 9 python merge dataframe pandas
我正在尝试合并两个数据帧,并用右df替换左df中的nan,我可以用以下三行代码来做到这一点,但是我想知道是否有更好/更短的方法?
# 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)
Run Code Online (Sandbox Code Playgroud)
混淆合并的问题是两个数据框都有一个“b”列,但左右版本在不匹配的地方有 NaN。你要避免不必要的越来越多“B”列“B_X”,“b_y”merge摆在首位:
merge(df2, 'left'),这将从正确的数据帧中选取“b”(因为它只存在于正确的 df 中)df1.update(...),这将更新从 df2 中获取的列 'b' 中的 NaNdf1['b']解决方案:
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
Run Code Online (Sandbox Code Playgroud)
注意: 因为我使用了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
Run Code Online (Sandbox Code Playgroud)
结果是
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
Run Code Online (Sandbox Code Playgroud)
正如预期的那样。
如果您想在可能涉及更多列时更明确
df1.update(df1.drop('b', 1).merge(df2, 'left', 'a'))
Run Code Online (Sandbox Code Playgroud)
如果您不想update使用数据框,我们可以使用combine_first
快的
df1.combine_first(df1[['a', 'e']].merge(df2, 'left'))
Run Code Online (Sandbox Code Playgroud)
显式
df1.combine_first(df1.drop('b', 1).merge(df2, 'left', 'a'))
Run Code Online (Sandbox Code Playgroud)
该'left' merge可维持秩序,但不是指标。这是超保守的方法:
df3 = df1.drop('b', 1).merge(df2, 'left', on='a').set_index(df1.index)
df1.combine_first(df3)
Run Code Online (Sandbox Code Playgroud)
简洁版本
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
Run Code Online (Sandbox Code Playgroud)
既然您提到过,会有多列
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
Run Code Online (Sandbox Code Playgroud)
我们也可以通过fillnadf
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
Run Code Online (Sandbox Code Playgroud)