You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何按条件合并Pandas DataFrame(支持通配符匹配)

带通配符的DataFrame条件合并(精确匹配优先)

我有两个DataFrame:

import pandas as pd

df1 = pd.DataFrame([['A', 'B', 'C'], ['D', 'E', 'F'], ['A', 'B', 'D'], ['H', 'I', 'J']],
                   columns=['Key1', 'Key2', 'Key3'])
df2 = pd.DataFrame([['A', 'B', '*', 25], ['D', 'E', 'F', 50], ['*', '*', '*', 100]], 
                   columns=['Key11', 'Key21', 'Key31', 'Value'])

它们的结构如下:

  • df1:
Key1Key2Key3
ABC
DEF
ABD
HIJ
  • df2:
Key11Key21Key31Value
AB*25
DEF50
***100
  • 期望输出:
Key1Key2Key3Value
ABC25
DEF50
ABD25
HIJ100

需求是按条件合并df1和df2:优先匹配精确键值,若未找到匹配项,则匹配包含通配符*的键规则(即每个键满足左表键 == 右表键或右表键 == '*')。我尝试过merge结合query的方式但未成功,示例代码如下:

query_line = "(Key1 == Key11 | Key11 == '*') & (Key2 == Key21 | Key21 == '*') & (Key3 == Key31| Key31 == '*')"
out = df1.merge(df2, left_on=['Key1', 'Key2', 'Key3'],
                right_on=['Key11', 'Key21', 'Key31'], how='left').query(query_line)

请给出正确的实现方法。


解决方案

思路

核心逻辑是为每个df1的行计算与df2各规则的匹配优先级,精确匹配的键数量越多,优先级越高。最终为每个df1行选择优先级最高的规则对应的Value。

实现代码

import pandas as pd

# 定义原始DataFrame
df1 = pd.DataFrame([['A', 'B', 'C'], ['D', 'E', 'F'], ['A', 'B', 'D'], ['H', 'I', 'J']],
                   columns=['Key1', 'Key2', 'Key3'])
df2 = pd.DataFrame([['A', 'B', '*', 25], ['D', 'E', 'F', 50], ['*', '*', '*', 100]], 
                   columns=['Key11', 'Key21', 'Key31', 'Value'])

# 生成笛卡尔积,获取所有可能的组合
merged = df1.assign(temp=1).merge(df2.assign(temp=1), on='temp').drop('temp', axis=1)

# 计算匹配得分:统计精确匹配的键数量
merged['match_score'] = (
    (merged['Key1'] == merged['Key11']) +
    (merged['Key2'] == merged['Key21']) +
    (merged['Key3'] == merged['Key31'])
)

# 过滤不符合通配符规则的组合
valid_mask = (
    (merged['Key11'] == '*') | (merged['Key1'] == merged['Key11'])
) & (
    (merged['Key21'] == '*') | (merged['Key2'] == merged['Key21'])
) & (
    (merged['Key31'] == '*') | (merged['Key3'] == merged['Key31'])
)
merged = merged[valid_mask]

# 按df1行分组,选择得分最高的匹配项
result = merged.sort_values('match_score', ascending=False).groupby(['Key1', 'Key2', 'Key3']).first().reset_index()

# 保留目标列
result = result[['Key1', 'Key2', 'Key3', 'Value']]

print(result)

代码说明

  1. 笛卡尔积合并:通过临时列实现全连接,确保不遗漏任何潜在的匹配规则组合。
  2. 匹配得分计算:用精确匹配的键数量作为优先级依据,得分越高匹配度越高。
  3. 无效组合过滤:剔除那些右表键既不是*也不等于左表键的无效组合。
  4. 最优匹配选择:按df1的行分组,排序后取得分最高的项,保证每个df1行只保留优先级最高的Value。

运行后输出结果与期望完全一致。

内容的提问来源于stack exchange,提问作者LUIS BLEDA TORRES

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 05:18:18