基于多列条件逻辑的Pandas DataFrame内连接实现咨询
基于多列条件逻辑的Pandas DataFrame内连接实现咨询
嘿,我懂你想要的这种「递进式匹配」内连接确实有点绕,但完全可以实现!先把你的数据和需求理得更清楚些:
首先是你给出的两个DataFrame结构:
import pandas as pd import numpy as np conditions = pd.DataFrame({ 'keywords_0':["a", "c", "e"], 'keywords_1':["b", "d", "f"], 'keywords_2':["00", "01", "02"], 'price': [1, 2 ,3] }) target = pd.DataFrame({ 'keywords_0':["a", "c", "e"], 'keywords_1':["b", "d", np.nan], 'keywords_2':["00", np.nan, np.nan] })
你的核心需求是:做内连接时,按从左到右的关键字列递进匹配——先匹配keywords_0,如果target的下一列(比如keywords_1)非空,就必须同时匹配该列;如果该列是空值,就只用到前面已匹配的列(不再往下要求匹配)。
实现思路
我们可以通过给target的每行标记「匹配深度」来实现:也就是确定每行需要用到前几个关键字列去匹配conditions,然后拆分target成不同子集,分别做对应列的内连接,最后合并结果。
具体代码实现
# 第一步:定义关键字列的顺序 keyword_cols = ['keywords_0', 'keywords_1', 'keywords_2'] # 第二步:给target计算每行的匹配深度——即需要用到前n个关键字列 target['match_depth'] = target[keyword_cols].isna().idxmax(axis=1).map(keyword_cols.index) # 处理所有列都非空的情况(idxmax会返回False,map后为-1,这里修正为列数) target['match_depth'] = target['match_depth'].replace(-1, len(keyword_cols)) # 第三步:按匹配深度拆分target,分别连接后合并 result_dfs = [] for depth in target['match_depth'].unique(): # 取出当前深度需要用到的关键字列 use_cols = keyword_cols[:depth] # 内连接两个DataFrame temp_df = pd.merge( conditions, target[use_cols + ['match_depth']], on=use_cols, how='inner' ) result_dfs.append(temp_df) # 合并所有结果,去掉辅助列match_depth final_result = pd.concat(result_dfs, ignore_index=True).drop('match_depth', axis=1) print(final_result)
运行后会得到符合预期的结果:
keywords_0 keywords_1 keywords_2 price 0 a b 00 1 1 c d 01 2 2 e f 02 3
代码解释
match_depth的计算:通过isna().idxmax(axis=1)找到每行第一个空值所在的列,再转换成该列在关键字列表中的索引,这样就明确了每行需要用到前几列匹配。比如target第三行的keywords_1是空值,所以match_depth为1,只需要用keywords_0匹配。- 拆分后分别连接:确保每个子集都用对应的关键字列去匹配
conditions,最后合并结果,完美实现了你要的递进式匹配逻辑。
如果你的关键字列更多,只需要修改keyword_cols列表即可,这个方法是通用的。
备注:内容来源于stack exchange,提问作者euh
相关产品推荐
相关产品推荐

