pandas 跨多列搜索如果匹配则返回一列

问题描述 投票:0回答:1

示例数据:

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 不强制具有相同的行数。

python pandas dataframe
1个回答
0
投票

只需将

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
© www.soinside.com 2019 - 2024. All rights reserved.