使用Pandas透视表统计重复值:首次正常,二次调用报错
问题原因与解决方法
问题根源
你遇到的KeyError: 'no of dups'是可变参数被意外污染导致的:
- 列表是可变对象,代码里的
targetColumns.extend(['no of dups'])会直接修改传入的targetColumns本身,而非创建新列表。 - 首次调用时,
targetColumns是干净的分组列(比如['account', 'year']),但调用结束后这个列表已被追加了'no of dups'。如果Django请求处理中复用了这个参数(比如参数存在全局变量、缓存或复用的上下文对象里),第二次调用时targetColumns就变成了['account', 'year', 'no of dups']。 - 而你读取的Excel文件里根本没有
'no of dups'列,pivot_table用这个列表作为分组key时,自然找不到对应列,抛出KeyError。
另外代码还有个隐性bug:res.reset_index()没有赋值给res,pandas多数方法默认返回新对象,不会修改原对象,这行代码等于没执行,后续的res.rename操作实际是在操作Series而非DataFrame,逻辑存在混乱。
解决方法
1. 禁止直接修改传入的可变参数
永远不要修改函数的可变参数(列表、字典等),创建副本后再操作:
把targetColumns.extend(['no of dups'])替换为:
# 创建副本,避免污染原参数 result_columns = targetColumns.copy() result_columns.append('no of dups') # 或更简洁的写法 result_columns = targetColumns + ['no of dups']
之后用result_columns做过滤:
res = res.filter(result_columns).values.tolist()
2. 简化pivot_table处理逻辑
直接在pivot_table步骤完成计数列命名,避免后续的rename和reset_index混乱:
# 一步生成带计数列的DataFrame res = dfTable.pivot_table(index=targetColumns, aggfunc='size').reset_index(name='no of dups')
修复后的完整代码
def duplicationCount(table_file_path, targetColumns): dfTable = pd.read_excel(io=table_file_path, sheet_name='Sheet1', skiprows=0) dfTable.columns = dfTable.columns.str.strip("'") # 一步生成统计结果DataFrame res = dfTable.pivot_table(index=targetColumns, aggfunc='size').reset_index(name='no of dups') # 过滤重复次数≥2的记录 res = res[res['no of dups'] >= 2] # 基于原参数创建结果列,不修改原列表 result_columns = targetColumns + ['no of dups'] res = res.filter(result_columns).values.tolist() return res
验证逻辑
修复后,无论调用多少次,传入的targetColumns都不会被修改,每次都会基于原始分组列统计,不会再出现找不到'no of dups'列的问题。同时简化后的pandas操作逻辑更清晰,也解决了原代码的隐性bug。
内容的提问来源于stack exchange,提问作者SDido
相关产品推荐
相关产品推荐

