使用Python的Groupby与Lambda函数计算赛马胜率
赛马数据集分组统计解决方案
你的代码目前存在两个核心问题:一是两次单独分组处理效率低下(尤其针对1200多万行的大数据),二是用sum统计参赛次数逻辑错误——参赛总次数应该是每组的记录行数,而非horse_id的求和。下面是高效的完整实现方案:
import pandas as pd # 数据合并(你的原有代码逻辑没问题,直接保留) race_db = pd.read_csv('horse_race_data_db.csv') race_db_2 = pd.read_csv('2_horse_race_data.csv') race_dbs = pd.concat([race_db, race_db_2], ignore_index=True, sort=False) # 一次分组完成所有统计需求 horse_stats = race_dbs.groupby('horse_id').agg( wins=('place', lambda col: (col == 1).sum()), # 统计place=1的获胜次数 races=('race_id', 'count') # 每组的行数即为该马的参赛总次数 ).reset_index() # 将分组用的horse_id从索引转为普通列 # 计算胜率,处理可能的除0异常(若存在无参赛记录的马) horse_stats['win rate'] = horse_stats['wins'] / horse_stats['races'].replace(0, 1) # 可选:将胜率保留四位小数,提升可读性 horse_stats['win rate'] = horse_stats['win rate'].round(4) # 查看结果示例 print(horse_stats.head())
关键细节说明
- 高效分组:用
agg方法一次性指定多个统计规则,避免重复执行groupby,处理千万级数据时速度提升明显。 - 获胜次数统计:
(col == 1).sum()比你原代码的x[x==1].count()更简洁高效,布尔值会自动转换为1/0,求和直接得到获胜次数。 - 参赛次数统计:用
race_id的count统计每组行数,因为数据集每行对应一次参赛记录,count结果就是该马的总参赛次数。 - 格式适配:
reset_index()将分组索引horse_id转为普通列,完全匹配你需要的输出列结构。 - 异常防护:
replace(0,1)是为了避免出现某匹马无参赛记录(races=0)时的除0报错,若确认所有马都有参赛记录,可省略此步。
最终输出的horse_stats会包含horse_id、wins、races、win rate四列,完全符合你的需求。
内容的提问来源于stack exchange,提问作者Ed Lee
相关产品推荐
相关产品推荐

