pandas 合并不同列的公共单元值上的两个 Dataframe

fsi0uk1n  于 2022-11-27  发布在  其他
关注(0)|答案(2)|浏览(125)

我有两个 Dataframe

df1 = pd.DataFrame({'col1': [1,2,3], 'col2': [4,5,6]})
df2 = pd.DataFrame({'col3': [1,5,3]})

并且希望将df1左合并到df2。但是,我在df1中没有固定的合并列。如果col1的单元格值存在于df2.col3中,我希望在col1上合并,如果col2的单元格值存在于df2.col3中,我希望在col2上合并。因此,在上面的示例中,在col1上合并,col2,然后是col1。(这只是一个例子,我实际上不止有两列)。我可以这样做,但我不确定这样做是否合适。

df1 = df1.assign(merge_col = np.where(df1.col1.isin(df2.col3), df1.col1, df1.col2))
df1.merge(df2, left_on='merge_col', right_on='col3', how='left')

有没有更好的解决办法?

nhaq1z21

nhaq1z211#

按首选顺序执行合并,并使用combine_first合并合并:

(df1.merge(df2, left_on='col1', right_on='col3', how='left')
    .combine_first(df1.merge(df2, left_on='col2', right_on='col3', how='left')
                  )
)

对于具有许多列的泛型方法:

cols = ['col1', 'col2']

from functools import reduce

out = reduce(
  lambda a,b: a.combine_first(b),
  [df1.merge(df2, left_on=col, right_on='col3', how='left')
   for col in cols]
)

输出量:

col1  col2  col3
0     1     4   1.0
1     2     5   5.0
2     3     6   3.0

更好的示例:将另一列添加到df2以说明合并:

df2 = pd.DataFrame({'col3': [1,5,3], 'new': ['A', 'B', 'C']})

输出量:

col1  col2  col3 new
0     1     4   1.0   A
1     2     5   5.0   B
2     3     6   3.0   C
w8rqjzmb

w8rqjzmb2#

我认为您的解决方案可以修改为获取合并的Series,比较列表中的所有列,然后合并此Series
s的解释:按DataFrame.isin比较所有列,如果按DataFrame.where不匹配,则创建缺失值,对于优先级,使用按位置选择第一列来填充缺失值:

cols = ['col1', 'col2']

s = df1[cols].where(df1[cols].isin(df2.col3)).bfill(axis=1).iloc[:, 0]
print (s)
0    1.0
1    5.0
2    3.0
Name: col1, dtype: float64

df = df1.merge(df2, left_on=s, right_on='col3', how='left')
print (df)
   col1  col2  col3
0     1     4     1
1     2     5     5
2     3     6     3

您的解决方案与帮助器列:

cols = ['col1', 'col2']

df1 = (df1.assign(merge_col = = df1[cols].where(df1[cols].isin(df2.col3))
                                         .bfill(axis=1).iloc[:, 0]))
df = df1.merge(df2, left_on='merge_col', right_on='col3', how='left')

print (df)
   col1  col2  merge_col  col3
0     1     4        1.0     1
1     2     5        5.0     5
2     3     6        3.0     3

s的解释:按DataFrame.isin比较所有列,如果按DataFrame.where不匹配,则创建缺失值,对于优先级,使用按位置选择第一列来填充缺失值:

print (df1[cols].isin(df2.col3))
    col1   col2
0   True  False
1  False   True
2   True  False

print (df1[cols].where(df1[cols].isin(df2.col3)))
   col1  col2
0   1.0   NaN
1   NaN   5.0
2   3.0   NaN

print (df1[cols].where(df1[cols].isin(df2.col3)).bfill(axis=1))
   col1  col2
0   1.0   NaN
1   5.0   5.0
2   3.0   NaN

print (df1[cols].where(df1[cols].isin(df2.col3)).bfill(axis=1).iloc[:, 0])
0    1.0
1    5.0
2    3.0
Name: col1, dtype: float64

相关问题