Pandas模糊匹配CSV报Columns must be same length as key错误解决
报错根因排查
- 触发
ValueError: "Columns must be same length as key"的直接原因:自定义函数fn没有定义未匹配场景的返回值,当df1中的机构名在df2找不到对应结果时,函数默认返回None,导致apply输出的结果长度和待赋值的2个列数不匹配。 - 原代码其余逻辑错误:
- df2读取路径错误,代码中写的是读取
file1.csv,实际应该读取file2.csv - 字段引用完全错误:给两个df加前缀后,没有对应修改函数内的字段名,函数中调用的
research_groups_names_f1、research_groups_names_f2字段在加前缀后的df中根本不存在 - 匹配逻辑写反:原判断条件交叉引用了两个表的字段,根本无法执行正确的名称比对
- 返回值不符合要求:函数匹配命中时直接返回整行Series,没有做字段对齐,也没有按要求给未匹配项填充
Not found - 性能极差:逐行通过
iterrows遍历df2做匹配,5000行df1加15000行df2总共要做7500万次比对,运行效率极低。
- df2读取路径错误,代码中写的是读取
可直接运行的正确实现
匹配逻辑按优先级设置:先做完全精确匹配,再做缩写、子串包含匹配,避免短关键词误匹配,未匹配项统一填充Not found,同时优化遍历逻辑提升运行速度。
import pandas as pd # 读取两个源文件 df1 = pd.read_csv('file1.csv') df2 = pd.read_csv('file2.csv') # 预处理:去除名称前后多余空格,避免格式问题导致匹配失败 df1['research_groups_names_f1'] = df1['research_groups_names_f1'].str.strip() df2['research_groups_names_f2'] = df2['research_groups_names_f2'].str.strip() # 提前把df2的机构名、地理位置转成列表,减少循环内的pandas对象读取开销 f2_list = df2[['research_groups_names_f2', 'Locatio_f2']].values.tolist() def match_rule(f1_org_name): # 第一优先级:完全精确匹配 for f2_org_name, location in f2_list: if f1_org_name == f2_org_name: return pd.Series([f2_org_name, location]) # 第二优先级:缩写/子串匹配 for f2_org_name, location in f2_list: # 匹配规则:f1名称是f2全称的子串(如CAS匹配带(CAS)的全称),或f2括号内缩写和f1名称完全一致 abbr = f2_org_name.split('(')[-1].replace(')', '').strip() if '(' in f2_org_name else '' if f1_org_name in f2_org_name or abbr == f1_org_name: return pd.Series([f2_org_name, location]) # 未命中任何规则,返回默认值 return pd.Series(['Not found', 'Not found']) # 执行匹配赋值 df1[['research_groups_names_f2', 'Locatio_f2']] = df1['research_groups_names_f1'].apply(match_rule) # 导出结果文件,保留要求的三个字段 df1.to_csv('file_output.csv', index=False, encoding='utf-8-sig') print("匹配完成,结果已写入file_output.csv") print(df1.head())
优化提示
- 如果对匹配准确率要求更高,可以补充机构名标准化规则,比如统一大小写、去除特殊符号、配置专属别名映射,避免大小写差异、符号差异导致的漏匹配
- 如果数据量进一步增大,可以改用字符串模糊匹配库(如rapidfuzz)按相似度阈值匹配,准确率和性能都会比纯子串匹配更好
内容的提问来源于stack exchange,提问作者DaviComputerVision
相关产品推荐
相关产品推荐

