Pandas基于file列判断学生是否重考生成新列时出现KeyError: 'file'的解决方法
解决KeyError: 'file'的问题并实现重考判断需求
问题原因
你遇到的KeyError: 'file'是因为在调用pivot_table时,把'file'放到了index参数里,这时候它不再是DataFrame的普通列,而是变成了**多层索引(MultiIndex)**的一部分。当你用apply遍历df_math的行时,res代表的是行数据,里面没有名为'file'的列,自然会抛出找不到键的错误。
方案一:跳过pivot_table,直接在原DataFrame上实现需求
其实你的需求不需要先做透视表,直接在原始数据上处理会更简单高效:
- 先给每行标记是否为当前重考记录
- 按学生(结合班级、科目确保维度准确)分组,判断该学生是否存在过重考记录
代码示例:
import pandas as pd df = pd.DataFrame(columns=['file', 'class', 'student', 'subject', 'scores'], data=[['re_test', 'A', 'John', 'Math', 60], ['first_test', 'A', 'Scott', 'Math', 75], ['first_test', 'A', 'Mary', 'Math', 80], ['re_test', 'B', 'Jack', 'Math', 70], ['first_test', 'B', 'Mina', 'Math', 75], ['first_test', 'B', 'James', 'Math', 95]]) # 给每行标记是否为单次重考记录 df['is_re_test'] = df['file'].str.contains('re') # 按分组维度判断学生是否有过重考历史,同步到每一行 df['Re-test'] = df.groupby(['class', 'student', 'subject'])['is_re_test'].transform('any').map({True: 'Yes', False: 'No'}) print(df)
运行后会给原始数据的每一行都正确标记该学生是否有过重考记录,完全匹配你的需求。
方案二:如果一定要保留pivot_table的使用
如果你坚持要用透视表的方式,需要从多层索引中提取file的值——此时file是索引的一部分,可以通过res.name获取索引元组(你的索引顺序是['class', 'student', 'file'],元组的第三个元素就是file的值):
修改你的代码如下:
df_math= df.pivot_table(index= ['class', 'student', 'file'], values=['subject'], aggfunc=['count'], fill_value = 0) def retest_check(res): # 从索引元组中提取file字段的值 file_value = res.name[2] return 'Yes' if 're' in file_value else 'No' df_math['Re-test'] = df_math.apply(retest_check, axis=1) print(df_math)
这样就能正确获取到file的值,避免KeyError的出现。
补充说明
对比两种方案,第一种更贴合你的需求场景:它保留了原始数据的所有行信息,同时给每个学生的每一条记录都标记了重考状态;而第二种透视表的方式会聚合数据,可能丢失原始行的细节。更推荐使用第一种方案。
内容的提问来源于stack exchange,提问作者Kelvin Lo
相关产品推荐
相关产品推荐

