如何在DataFrame中使用通配符实现类VLOOKUP匹配?
通配符匹配下的类VLOOKUP实现(基于Pandas)
问题说明
需要用带通配符*的参考DataFrame匹配目标DataFrame,返回每行的匹配结果。之前尝试用字符串拼接生成多列组合过滤,需要维护大量拼接列,扩展性差,寻求更优方案。
参考DataFrame(含通配符*)
A B C 0 1 1 1 1 3 * y 2 x * * 3 x 4 7 4 1 7 9 5 * 1 z 6 y 1 0 7 3 1 6
目标DataFrame
A B C 0 3 2 y 1 x 5 6 2 2 7 8 4 y 1 0
预期匹配结果
A B C Result 0 3 2 y match 1 x 5 6 match 2 2 7 8 no match 4 y 1 0 match
最优实现方案
核心思路是逐行验证目标数据是否符合参考数据中的任意一条规则(*匹配任意值),用Pandas的向量化操作替代繁琐的字符串拼接,提升效率和可维护性。
基础版代码(小数据量适用)
import pandas as pd # 构建参考与目标DataFrame ref_df = pd.DataFrame({ 'A': ['1', '3', 'x', 'x', '1', '*', 'y', '3'], 'B': ['1', '*', '*', '4', '7', '1', '1', '1'], 'C': ['1', 'y', '*', '7', '9', 'z', '0', '6'] }) target_df = pd.DataFrame({ 'A': ['3', 'x', '2', 'y'], 'B': ['2', '5', '7', '1'], 'C': ['y', '6', '8', '0'] }, index=[0,1,2,4]) # 单条规则匹配判断:检查目标行是否符合某条参考规则 def check_match(target_row, ref_row): return all(val == '*' or val == target_row[col] for col, val in ref_row.items()) # 对目标每行,判断是否存在匹配的参考规则 target_df['Result'] = target_df.apply( lambda row: 'match' if any(check_match(row, ref_df.iloc[i]) for i in range(len(ref_df))) else 'no match', axis=1 ) print(target_df)
大数据量优化版(向量化实现)
如果数据量较大,上面的逐行遍历效率偏低,可以用Numpy广播机制实现全向量化匹配,彻底避免Python循环:
import pandas as pd import numpy as np ref_df = pd.DataFrame({ 'A': ['1', '3', 'x', 'x', '1', '*', 'y', '3'], 'B': ['1', '*', '*', '4', '7', '1', '1', '1'], 'C': ['1', 'y', '*', '7', '9', 'z', '0', '6'] }) target_df = pd.DataFrame({ 'A': ['3', 'x', '2', 'y'], 'B': ['2', '5', '7', '1'], 'C': ['y', '6', '8', '0'] }, index=[0,1,2,4]) # 转换为numpy数组,利用广播做批量匹配 ref_arr = ref_df.to_numpy() target_arr = target_df.to_numpy() # 生成匹配掩码:每个目标行 vs 每个参考行的每列是否匹配 match_cols = (ref_arr == '*') | (ref_arr == target_arr[:, None, :]) # 每条参考规则是否全列匹配,再判断每个目标行是否有至少一条匹配规则 has_match = match_cols.all(axis=2).any(axis=1) # 生成结果列 target_df['Result'] = np.where(has_match, 'match', 'no match') print(target_df)
方案优势
- 无需维护大量拼接列,规则调整直接修改参考DataFrame即可
- 基础版逻辑直观,易理解和调试;优化版利用向量化操作,处理十万级以上数据时效率提升明显
内容的提问来源于stack exchange,提问作者Kenny
相关产品推荐
相关产品推荐

