You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 18:55:31