Pandas DataFrame多条件统计正误答案数的最优实现方法
问题背景
- 待处理数据为1580行×48列的Pandas DataFrame,每列存储对应问题的受访者作答结果,单元格值为
NaN代表对应受访者未回答该题 - 所有问题按关联关系划分为9个题组,每个题组已提前整理好对应的正确答案列表
- 需要为每个题组统计生成两个结果列:
c_answers:组内答对题数i_answers:组内答错题数
- 统一统计规则:逐行校验题组内每列取值
- 取值在正确答案列表中:
c_answers计数加1 - 取值非
NaN且不在正确答案列表中:i_answers计数加1 - 取值为
NaN:两类计数均不累计
- 取值在正确答案列表中:
- 要求统计逻辑可复用到全部9个题组,避免逐列编写重复代码、生成冗余中间列
现有实现问题
当前方案通过嵌套np.where()逐列生成单题得分字段,再对分数字段求和推导正误计数,最后删除过程中生成的中间列,代码冗余、维护成本高。
测试用例代码:
import pandas as pd import numpy as np ex_df = pd.DataFrame([["a", "b", "d"],[np.nan, "a", "b"], ["c", "e", np.nan]], columns=["q1", "q2", "q3"]) correct_answers = ["a", "b", "c"]
原始测试DataFrame:
q1 q2 q3 0 a b d 1 NaN a b 2 c e NaN
逐列计分示例代码:
ex_df['q1score'] = np.where(ex_df['q1'].isna(), np.nan, np.where(ex_df['q1'].isin(correct_answers), 1, 100))
单题计分输出:
q1 q2 q3 q1score 0 a b d 1.0 1 NaN a b NaN 2 e c NaN 100.0
预期最终输出:
q1 q2 q3 c_answers i_answers 0 a b d 2 1 1 NaN a b 2 0 2 e c NaN 1 1
最优实现方案
核心思路是利用Pandas向量化运算避免逐列循环,不生成临时中间列,将统计逻辑封装为可复用函数,直接针对题组列批量计算,代码简洁且运行效率远高于逐列处理。
步骤1:封装可复用统计函数
def score_question_group(df, group_cols, correct_ans, c_col='c_answers', i_col='i_answers'): """ 统计指定题组的答对、答错题数 参数: df: 原始作答DataFrame group_cols: 列表,当前题组包含的列名 correct_ans: 列表,当前题组的正确答案集合 c_col: 答对计数的输出列名,默认c_answers i_col: 答错计数的输出列名,默认i_answers """ # 截取当前题组的所有作答列 group_data = df[group_cols] # 向量化判断每个单元格是否为正确答案,NaN自动判定为False is_correct = group_data.isin(correct_ans) # 逐行求和得到答对总题数 df[c_col] = is_correct.sum(axis=1) # 答错题数 = 有效作答数(非空单元格数)- 答对题数 df[i_col] = group_data.notna().sum(axis=1) - df[c_col] return df
步骤2:验证函数效果
调用函数处理测试数据:
ex_df = score_question_group(ex_df, group_cols=['q1','q2','q3'], correct_ans=correct_answers) print(ex_df)
输出完全匹配预期结果:
q1 q2 q3 c_answers i_answers 0 a b d 2 1 1 NaN a b 2 0 2 c e NaN 1 1
步骤3:批量复用处理所有题组
提前整理好9个题组的列名、对应正确答案、输出列名配置,循环调用函数即可完成全量统计,无需重复编写逻辑:
# 提前整理所有题组配置 question_groups = [ {"cols": ["q1","q2","q3"], "correct": ["a","b","c"], "c_name": "g1_c", "i_name": "g1_i"}, {"cols": ["q4","q5","q6"], "correct": ["x","y"], "c_name": "g2_c", "i_name": "g2_i"}, # 剩余7个题组按相同格式补充即可 ] # 批量统计所有题组 for g in question_groups: ex_df = score_question_group( df=ex_df, group_cols=g["cols"], correct_ans=g["correct"], c_col=g["c_name"], i_col=g["i_name"] )
该方案无冗余中间列、运行效率高、后续维护成本低,符合Pandas最佳实践。
内容的提问来源于stack exchange,提问作者WJTownsend
相关产品推荐
相关产品推荐

