在Pandas DataFrame中通过条件概率生成运动员距离偏好列
问题描述
我有一个包含运动员赛事数据的大型Pandas DataFrame,结构如下:
Race_ID Athlete_ID Distance Rank 1 1 100 3 2 1 400 6 3 1 1500 1 4 1 100 6 5 1 100 1 6 1 1500 1 7 2 100 1 8 2 400 2 9 2 400 1 10 2 1500 6 11 2 1500 4 12 2 100 1 13 2 100 1
需要新增一列Dist_Preference,通过计算运动员在各距离赛事中获胜的条件概率(即该距离下获胜次数/该距离参赛总次数),判断其最擅长的距离(100米/400米/1500米)。例如运动员1的各距离胜率:
- 100米:2/3
- 400米:0/1
- 1500米:2/2
因此其Dist_Preference为1500,最终期望DataFrame如下:
Race_ID Athlete_ID Distance Rank Dist_Preference 1 1 100 3 1500 2 1 400 6 1500 3 1 1500 1 1500 4 1 100 6 1500 5 1 100 1 1500 6 1 1500 1 1500 7 2 100 1 100 8 2 400 2 100 9 2 400 1 100 10 2 1500 6 100 11 2 1500 4 100 12 2 100 1 100 13 2 100 1 100
之前用.apply()方法实现时,处理大型DataFrame速度极慢,求更高效的实现方式。
高效实现方案
使用Pandas的向量化分组聚合操作替代apply(),完全利用Pandas内部优化,大幅提升处理速度,步骤如下:
步骤1:标记获胜记录
新增一列标记是否获胜(默认Rank=1即为获胜):
df['is_win'] = df['Rank'] == 1
步骤2:计算各运动员-距离的胜率
按Athlete_ID和Distance分组,聚合计算获胜次数和总参赛次数,再算出胜率:
# 分组聚合:统计每个运动员在每个距离下的获胜次数、总参赛次数 athlete_dist_stats = df.groupby(['Athlete_ID', 'Distance']).agg( win_count=('is_win', 'sum'), total_count=('is_win', 'size') ).reset_index() # 计算胜率 athlete_dist_stats['win_rate'] = athlete_dist_stats['win_count'] / athlete_dist_stats['total_count']
步骤3:确定每个运动员的最优距离
按Athlete_ID分组,找到胜率最高的Distance(若有多个距离胜率相同,可根据需求调整排序规则):
# 按胜率降序排序,每组取第一个(胜率最高的距离) athlete_preference = athlete_dist_stats.sort_values('win_rate', ascending=False)\ .groupby('Athlete_ID')['Distance'].first().reset_index(name='Dist_Preference')
步骤4:合并回原DataFrame
将运动员的偏好距离映射回原DataFrame的每一行:
df = df.merge(athlete_preference, on='Athlete_ID', how='left') # 可选:删除临时的is_win列 df = df.drop('is_win', axis=1)
优化说明
- 上述操作均为Pandas向量化操作,避免了
apply()的逐行/逐组循环,处理大型DataFrame时速度提升显著(通常快10~100倍) - 若存在多个距离胜率相同的情况,可修改
sort_values参数,比如加入Distance的排序规则,或用rank()方法处理并列场景
内容的提问来源于stack exchange,提问作者Apook
相关产品推荐
相关产品推荐

