示例数据:
df1 = pd.DataFrame({
'a': [1, 6, 3, 9],
'b': ['A', 'B', 'C', 'D'],
'c': [10, 20, 30, 40],
'd': [100, 200, 300, 400]
})
df2 = pd.DataFrame({
'm': [1, 5, 3, 7],
'n': [2, 6, 8, 4],
'o': [9, 10, 11, 12]
})
要求:
df1['a']
可以出现在 df2
的任何地方。无论在哪里找到匹配项,我都想返回 df2['m']
。
经过一些谷歌搜索和 chatGpt 后,我发现融化
df2
并与 df1
合并很有帮助,除了它不检查 df2['m']
中的匹配。
代码:
df2_melted = df2.melt(id_vars=['m'], value_vars=['n', 'o'])
merged_df = df1.merge(df2_melted, left_on='a', right_on='value', how='left')
df1['e'] = merged_df['m']
print(df1)
输出:
a b c d e
1 A 10 100 NaN # df1['a'] == df2['m']
6 B 20 200 5.0 # df1['a'] == df2['n']
3 C 30 300 NaN # df1['a'] == df2['m']
9 D 40 400 1.0 # df1['a'] == df2['o']
所需输出:
a b c d e
1 A 10 100 1
6 B 20 200 5
3 C 30 300 3
9 D 40 400 1
如果在熔化时也可以将
df2['m']
添加到value_vars
中,那就可以解决问题了。我试过了,没用。然后检查文档,发现无论id_vars
中有什么,剩余的或剩余的子集都可以是value_vars
的一部分。所以这种方法可能不正确或者我遗漏了一些东西。
然后我想,如果
df1['a']
匹配df2['m']
,那么df1['e'] == df1['a'] == df2['m']
。因此,只需将 NaN
值替换为 df1['a']
就可以了,而且确实有效。但必须将列转换为 int;因为NaN
,变成了浮动。
工作完整代码:
df2_melted = df2.melt(id_vars=['m'], value_vars=['n', 'o'])
merged_df = df1.merge(df2_melted, left_on='a', right_on='value', how='left')
df1['e'] = merged_df['m']
df1['e'] = (df1['e'].fillna(df1['a'])).astype(int)
虽然这是一个可行的解决方案,但它不必要地复杂:“尝试任何解决方案:在继续操作时添加更多代码来解决问题,而不更改初始解决方案”。
还有其他更好的方法可以帮助满足我的要求吗?
PS1:在上面的示例中,df1 和 df2 不强制具有相同的行数。
只需将
m
列复制为 melt
之前的新列(也使用 map
代替 merge
):
df1['e'] = df1['a'].map(df2.eval('e=m').melt('e')
.set_index('value')['e'])
输出:
a b c d e
0 1 A 10 100 1
1 6 B 20 200 5
2 3 C 30 300 3
3 9 D 40 400 1