DataFrame逐行应用函数异常:全列返回draw问题排查
解决DataFrame每行统计投票结果生成winner列的问题
嘿,我看出来你代码里的问题啦,这两个小错误导致所有结果都是draw:
问题1:对apply的参数理解错了
你写的函数里把x当成了行索引,用new_df.iloc[x]去取整行数据,但实际上当你用apply处理行的时候(需要指定axis=1),传入函数的x是当前行的Series对象,不是行号。而且你原来的调用df['winner_columns'].apply(winner)是在对空列(或已有列)按列处理,完全不是你想要的每行计算逻辑。
问题2:直接取value_counts()的键有风险
如果某行里没有'a'或者'b',直接写value_counts()['a']会抛出KeyError,用get方法设置默认值0会更安全。
修正后的代码
先改函数逻辑,直接对传入的行Series做统计:
def winner(row): # 统计当前行中'a'的数量,没有则返回0 count_a = row.value_counts().get('a', 0) # 统计当前行中'b'的数量,没有则返回0 count_b = row.value_counts().get('b', 0) if count_a > count_b: return 'a' elif count_a < count_b: return 'b' else: return 'draw'
然后正确调用apply,指定按行处理(axis=1),并把结果赋值给新列:
# 假设你的原始DataFrame名为df df['winner_columns'] = df.apply(winner, axis=1)
验证结果
用你给出的示例数据测试,运行后会得到完全符合预期的结果:
| vote_1 | vote_2 | vote_3 | vote_4 | winner_columns |
|---|---|---|---|---|
| a | a | a | b | a |
| b | b | a | b | b |
| b | a | a | b | draw |
更简洁的替代方案(无需自定义函数)
如果想少写点代码,也可以用eq和sum直接统计票数,再用lambda判断结果:
# 统计每行a和b的票数 df['count_a'] = df.eq('a').sum(axis=1) df['count_b'] = df.eq('b').sum(axis=1) # 生成winner列 df['winner_columns'] = df.apply( lambda row: 'a' if row['count_a'] > row['count_b'] else ('b' if row['count_a'] < row['count_b'] else 'draw'), axis=1 ) # 可选:删除中间的计数列 df = df.drop(['count_a', 'count_b'], axis=1)
这种方式在数据量较大时,效率可能比自定义函数更高哦~
内容的提问来源于stack exchange,提问作者CarterB
相关产品推荐
相关产品推荐

