如何修复透视DataFrame的报错及后续过滤问题?
解决透视表后基于索引项的过滤问题
你遇到的核心问题是透视后Category属于多层索引的一部分,无法直接通过列名df2['Category']访问,这会触发KeyError。另外原代码执行时,pivot_table会自动对包含NaN的行进行聚合(默认用mean),下面给出几种可行的解决方案:
方案1:直接通过索引层级过滤
利用index.get_level_values()获取指定层级的索引值,结合布尔索引完成过滤:
import numpy as np import pandas as pd df = pd.DataFrame({ 'Year':[2022,2022,2023,2023,2024,2024], 'Month':[1,12,11,12,1,1], 'Code':[None,'John Johnson',np.nan,'John Smith','Mary Williams','ted bundy'], 'Unit Price':[np.nan,200,None,56,75,65], 'Quantity':[1500, 140000, 1400000, 455, 648, 759], 'Amount':[100, 10000, 100000, 5, 48, 59], 'Invoice':['soccer','basketball','baseball','football','baseball','ice hockey'], 'energy':[100.,100,100,54,98,3], 'Category':['alpha','bravo','kappa','alpha','bravo','bravo'] }) index_to_use = ['Category','Code','Invoice','Unit Price'] values_to_use = ['Amount','Quantity'] columns_to_use = ['Year','Month'] df2 = df.pivot_table(index=index_to_use, values=values_to_use, columns=columns_to_use) # 基于索引的Category层级过滤 df3 = df2[df2.index.get_level_values('Category') == 'alpha'] # 写入Excel的代码不变 writer= pd.ExcelWriter( "t2test2.xlsx", engine='xlsxwriter' ) df.to_excel(writer,sheet_name="t2",index=True) df2.to_excel(writer,sheet_name="t2test",index=True) df3.to_excel(writer,sheet_name="t2filter",index=True) writer.close()
方案2:将索引层级转为列后过滤
如果更习惯用列操作逻辑,可以把索引的Category层转回列,再进行过滤:
# 透视表生成逻辑不变 df2 = df.pivot_table(index=index_to_use, values=values_to_use, columns=columns_to_use) # 将索引中的Category层级转为列 df2_reset = df2.reset_index(level='Category') # 按列过滤 df3 = df2_reset[df2_reset['Category'] == 'alpha'] # 可选:恢复原索引结构 df3 = df3.set_index('Category', append=True).reorder_levels(index_to_use)
方案3:透视前先过滤(更高效)
如果最终只需要Category='alpha'的数据,建议先过滤原DataFrame再执行透视,减少不必要的计算量:
# 先过滤原数据 df_filtered = df[df['Category'] == 'alpha'] # 对过滤后的数据执行透视 df2 = df_filtered.pivot_table(index=index_to_use, values=values_to_use, columns=columns_to_use) # 此时df2直接就是目标结果,无需二次过滤
额外注意事项
原数据中Code和Unit Price存在NaN值,pivot_table默认会对相同索引组合的行做均值聚合。如果不需要聚合、希望保留原始行数据(需确保索引组合唯一),可以指定聚合函数为'first':
df2 = df.pivot_table(index=index_to_use, values=values_to_use, columns=columns_to_use, aggfunc='first') # 保留第一个匹配的值,避免自动聚合
内容的提问来源于stack exchange,提问作者Alhpa Delta
相关产品推荐
相关产品推荐

