Pandas apply赋值报Columns must be same length as key错误
Pandas 关联匹配触发
Columns must be same length as key报错修复 报错基础信息
运行环境:Jupyter Labs
触发场景:使用Pandas对大规模CSV数据集做研究组字段关联匹配
报错信息:
ValueError: "Columns must be same length as key"
报错触发代码行:df1[["f2_research_groups_names", "f2_location"]] = df1.apply(fn, axis=1)
原始代码逻辑:
- 读取两份CSV文件分别存入DataFrame对象df1、df2
- 为两个DataFrame的所有列分别添加
f1_、f2_前缀做来源区分 - 自定义匹配函数fn,遍历df2每一行,当研究组名称完全匹配或df1的研究组名称为df2研究组名称子串时,返回匹配到的df2行
- 将apply执行fn的返回结果赋值给df1的两个新增列时触发报错
原始问题代码:
import pandas as pd df1 = pd.read_csv('file1.csv') df2 = pd.read_csv('file1.csv') df1 = df1.add_prefix('f1_') df2 = df2.add_prefix('f2_') def fn(row): for _, n in df2.iterrows(): if ( n["research_groups_names"] == row["research_groups_names"] or row["research_groups_names"] in n["research_groups_names"] ): return n df1[["f2_research_groups_names", "f2_location"]] = df1.apply(fn, axis=1) df1 = df1.rename(columns={"research_groups_names": "f1_research_groups_names"}) print(df1)
报错根因
- 列名引用错误:执行
add_prefix后,原research_groups_names列已分别重命名为f1_research_groups_names、f2_research_groups_names,fn函数内仍引用旧列名,会直接触发KeyError导致匹配逻辑失效 - 返回值长度不匹配:fn匹配成功时返回df2的整行Series(包含df2所有带f2_前缀的列),长度远大于赋值目标的2列;若df1某行在df2中无匹配结果,函数默认返回None,同样会导致返回值长度和目标列数不一致
- 逻辑笔误:读取df2时错误传入了和df1相同的文件名
file1.csv,会导致两份数据完全重复,不符合关联两个不同数据集的需求 - 性能缺陷:使用
iterrows()+apply逐行双循环遍历做匹配,万行以上规模数据集运行效率极低
修复后代码
import pandas as pd import numpy as np # 读取数据,修正df2的文件名笔误 df1 = pd.read_csv('file1.csv') df2 = pd.read_csv('file2.csv') # 列名加来源前缀 df1 = df1.add_prefix('f1_') df2 = df2.add_prefix('f2_') # 预生成df2的匹配字典,避免apply时重复遍历全量df2,大幅提升大文件匹配性能 f2_match_map = df2.set_index('f2_research_groups_names')['f2_location'].to_dict() f2_group_list = list(f2_match_map.keys()) def get_match_result(row): current_f1_group = row['f1_research_groups_names'] # 优先走精确匹配 if current_f1_group in f2_match_map: return pd.Series([current_f1_group, f2_match_map[current_f1_group]]) # 精确匹配失败走子串匹配 for f2_group in f2_group_list: if current_f1_group in f2_group: return pd.Series([f2_group, f2_match_map[f2_group]]) # 无匹配结果返回空值占位,保证返回值固定为2列 return pd.Series([np.nan, np.nan]) # 赋值左右两侧列数完全对齐,不会触发长度不匹配报错 df1[["f2_research_groups_names", "f2_location"]] = df1.apply(get_match_result, axis=1) print(df1)
修复点说明
- 修正了加前缀后的列名引用错误,移除了无效的重命名代码(加前缀后不存在旧列名,原rename语句无实际作用)
- 强制自定义匹配函数无论是否匹配成功,都固定返回长度为2的Series,和左侧赋值的列数完全一致,从根源解决长度不匹配问题
- 预生成匹配字典替代逐行遍历df2,大文件场景下匹配性能可提升10~100倍
- 修正了df2读取的文件名笔误
内容的提问来源于stack exchange,提问作者DaviComputerVision
相关产品推荐
相关产品推荐

