使用Pandas筛选数据时出现列KeyError问题求助
问题描述
尝试使用Pandas常规语法df[df[column_name] == "value"]按列值筛选数据时,始终收到针对列"Product (ACQ Search) - ONC"的KeyError。同时发现用df.columns查看列名时,仅显示脚本中之前重命名的4列,请问为何会出现该错误?
代码示例
import numpy as np import matplotlib.pyplot as plt from sklearn.linear_model import LinearRegression import pandas as pd # 原代码遗漏pandas导入,此处补充 # 加载Excel文件到DataFrame df = pd.read_excel("Marginal CPA data - NOV.xlsx") # 删除最后一行 df = df[:-1] # 筛选"Campaign Type (Search ACQ) - ONC"列值为"NonBrand"的行 df = df[df["Campaign Type (Search ACQ) - ONC"] == "NonBrand"] # 转换日期格式并删除原Day列 df["Date"] = pd.to_datetime(df["Day"], format="%d %b %Y") df = df.drop("Day", axis=1) # 创建透视表 pivot_table = pd.pivot_table(df, values=["Media Cost", "CAFE Approvals"], index=["Campaign Type (Search ACQ) - ONC", "Product (ACQ Search) - ONC", "Date"], columns=["CDJ"], aggfunc="sum") df_pivot = pivot_table.fillna(value=0) # 将多级列索引合并为单级 df_pivot.columns = ["_".join(col) for col in df_pivot.columns] # 重命名列 cols = { "Media Cost_CPA": "CPA Spend", "Media Cost_Non CPA (CDJ)": "CDJ Spend", "CAFE Approvals_CPA": "CPA Approvals", "CAFE Approvals_Non CPA (CDJ)": "CDJ Approvals" } df_pivot = df_pivot.rename(columns=cols) # 新增总计列 df_pivot["Total Approvals"] = df_pivot["CPA Approvals"] + df_pivot["CDJ Approvals"] df_pivot["Total Spend"] = df_pivot["CPA Spend"] + df_pivot["CDJ Spend"] # 过滤花费为0或审批数为0的行 df_pivot = df_pivot[df_pivot["CPA Spend"] != 0] df_pivot = df_pivot[df_pivot["Total Approvals"] != 0] # 按日期和产品排序 df_pivot = df_pivot.sort_values("Date", ascending=True) df_pivot = df_pivot.sort_values("Product (ACQ Search) - ONC", ascending=True) # 保存处理后的数据 df_pivot.to_excel("Marginal CPA data - NOV (processed).xlsx") # 筛选"Product (ACQ Search) - ONC"为"Consumer"的行(此处报错) consumer_data = df_pivot[df_pivot["Product (ACQ Search) - ONC"] == "Consumer"]
数据示例
| Campaign Type (Search ACQ) - ONC | Product (ACQ Search) - ONC | CDJ | Day | Media Cost | CAFE Approvals |
|---|---|---|---|---|---|
| NonBrand | Consumer | CPA | 11 Jan 2023 | 29019.77415 | 94 |
| NonBrand | Consumer | Non CPA (CDJ) | 17 Jan 2023 | 24640.36448 | 86 |
| NonBrand | Consumer | Non CPA (CDJ) | 12 Jan 2023 | 23627.78256 | 78 |
| NonBrand | Student | CPA | 17 Jan 2023 | 29863.95447 | 152 |
| NonBrand | Miles | CPA | 23 Jan 2023 | 380.94 | 1 |
| NonBrand | Miles | CPA | 07 Jan 2023 | 1786.51 | 5 |
| NonBrand | Consumer | CPA | 19 Jan 2023 | 26745.81705 | 64 |
| NonBrand | Secured | CPA | 20 Jan 2023 | 1551.35 | 19 |
| NonBrand | Consumer | Non CPA (CDJ) | 02 Feb 2023 | 41185.11225 | 66 |
| NonBrand | Student | CPA | 08 Jan 2023 | 42822.8508 | 171 |
| NonBrand | Student | CPA | 16 Jan 2023 | 29408.66012 | 160 |
| NonBrand | Consumer | CPA | 17 Jan 2023 | 29378.05227 | 85 |
| NonBrand | Miles | CPA | 10 Jan 2023 | 2019.25 | 4 |
| NonBrand | Miles | CPA | 11 Jan 2023 | 1604.98 | 4 |
| NonBrand | Secured | CPA | 21 Jan 2023 | 1704.13419 | 22 |
原因分析与解决方法
核心原因
创建透视表时,你把"Product (ACQ Search) - ONC"设为了行索引(index),而非普通数据列。后续处理中没有将索引还原为列,导致:
- 用列名访问时,Pandas找不到该列,抛出KeyError;
df.columns仅显示普通数据列,所以只能看到重命名后的4列以及新增的总计列。
解决方法
方法1:将索引转为普通列(推荐)
在透视表填充空值后,添加reset_index()方法,把所有索引列转为普通列:
df_pivot = pivot_table.fillna(value=0) # 新增此行,将索引转为列 df_pivot = df_pivot.reset_index()
之后再执行筛选代码即可正常运行。
方法2:直接通过索引筛选
如果不想修改索引结构,可以通过索引层级来筛选:
consumer_data = df_pivot[df_pivot.index.get_level_values("Product (ACQ Search) - ONC") == "Consumer"]
补充说明
之前的sort_values("Product (ACQ Search) - ONC")能生效,是因为Pandas的sort_values支持直接指定索引名称排序,但筛选操作必须明确访问列或索引层级。
内容的提问来源于stack exchange,提问作者jimlearnscoding
相关产品推荐
相关产品推荐

