使用janitor包conditional_join多条件匹配时遇TypeError问题求助
问题描述
需要基于以下三个条件,从查找表中为数据集匹配对应的Factor值:
- 数据集的
State与查找表的State_Cd完全匹配 - 数据集的
Deductible与查找表的Deductible完全匹配 - 数据集的
Revenue落在查找表的Revenue_1和Revenue_2区间内(满足Revenue_1 <= Revenue <= Revenue_2)
数据定义
查找表(Lookup_Table)
import pandas as pd Lookup_Table = {'State_Cd': ['TX','TX','TX','TX','CA','CA','CA','CA'], 'Deductible': [0,0,1000,1000,0,0,1000,1000], 'Revenue_1': [-99999999,25000000,-99999999,25000000,-99999999,25000000,-99999999,25000000], 'Revenue_2': [24999999,99000000,24999999,99000000,24999999,99000000,24999999,99000000], 'Factor': [0.15,0.25,0.2,0.3,0.11,0.15,0.13,0.45] } Lookup_Table = pd.DataFrame(Lookup_Table, columns = ['State_Cd','Deductible','Revenue_1','Revenue_2','Factor'])
数据集(Dataset)
Dataset = {'Policy': ['A','B','C'], 'State': ['CA','TX','TX'], 'Deductible': [0,1000,0], 'Revenue': [10000000,30000000,1000000] } Dataset = pd.DataFrame(Dataset, columns = ['Policy','State','Deductible','Revenue'])
预期输出
Policy State Deductible Revenue Factor 0 A CA 0 10000000 0.11 1 B TX 1000 30000000 0.30 2 C TX 0 1000000 0.15
报错情况
尝试使用janitor的conditional_join实现匹配时,出现如下错误:
尝试代码
import janitor Data_Final = (Dataset.conditional_join(Lookup_Table, ('Revenue', 'Revenue_1', '>='), ('Revenue', 'Revenue_2', '<='), ('State', 'State_Cd', '=='), ('Deductible', 'Deductible', '=='), how = 'left',sort_by_appearance = False ))
错误信息
TypeError: __init__() got an unexpected keyword argument 'copy'
问题原因与解决方案
该错误的核心原因是janitor版本与pandas版本不兼容:conditional_join内部调用的pandas API在新版本中移除了copy参数,但旧版janitor仍在传递该参数,导致报错。以下是三种可行的解决方法:
方案1:调整janitor版本
安装与当前pandas版本兼容的janitor版本,例如0.24.0版本(经测试适配多数较新pandas版本):
pip install pyjanitor==0.24.0
安装完成后重新运行原代码即可正常执行。
方案2:使用pandas原生方法实现
无需依赖janitor,通过merge+条件过滤的方式实现需求:
# 先按匹配字段合并两个表 merged = Dataset.merge( Lookup_Table, left_on=['State', 'Deductible'], right_on=['State_Cd', 'Deductible'], how='left' ) # 过滤满足Revenue区间条件的行 result = merged[(merged['Revenue'] >= merged['Revenue_1']) & (merged['Revenue'] <= merged['Revenue_2'])] # 保留需要的列并重置索引 result = result[['Policy', 'State', 'Deductible', 'Revenue', 'Factor']].reset_index(drop=True) print(result)
也可以用query方法简化过滤逻辑:
merged = Dataset.merge( Lookup_Table, left_on=['State', 'Deductible'], right_on=['State_Cd', 'Deductible'], how='left' ) result = merged.query('Revenue >= Revenue_1 and Revenue <= Revenue_2')[['Policy', 'State', 'Deductible', 'Revenue', 'Factor']].reset_index(drop=True)
方案3:用numpy广播实现匹配
针对小规模数据集,可通过numpy广播构建匹配矩阵,直接提取对应Factor:
import numpy as np # 构建匹配条件的布尔矩阵 match_mask = ( (Dataset['State'].values[:, None] == Lookup_Table['State_Cd'].values) & (Dataset['Deductible'].values[:, None] == Lookup_Table['Deductible'].values) & (Dataset['Revenue'].values[:, None] >= Lookup_Table['Revenue_1'].values) & (Dataset['Revenue'].values[:, None] <= Lookup_Table['Revenue_2'].values) ) # 提取匹配到的Factor值 Dataset['Factor'] = Lookup_Table['Factor'].values[np.argmax(match_mask, axis=1)] print(Dataset)
内容的提问来源于stack exchange,提问作者Bustergun
相关产品推荐
相关产品推荐

