Python报错求助:index 1 is out of bounds for axis 1 with size 0
问题与解决方案
问题详情
在对DataFrame执行for循环计算球队对战胜率时,循环执行427,942行后触发报错:
index 1 is out of bounds for axis 1 with size 0
相关代码:
自定义函数部分
outcome = [] def get_matchup(team_a_input, team_b_input, season_input): team_a = team_a_input team_b = team_b_input season = season_input team_a_stats = df.loc[(df.TeamID == team_a) & (df.Season == season)] team_a_results = team_a_stats['Result'] team_a_stats = team_a_stats.drop(['Result'], axis=1) team_b_stats = df.loc[(df.TeamID == team_b) & (df.Season == season)] team_b_results = team_b_stats['Result'] team_b_stats = team_b_stats.drop(['Result'], axis=1) probs_team_a = loaded_model.predict_proba(team_a_stats) probs_team_a = probs_team_a[:,1] loss_team_a = brier_score_loss(team_a_results, probs_team_a) probs_team_b = loaded_model.predict_proba(team_b_stats) probs_team_b = probs_team_b[:,1] loss_team_b = brier_score_loss(team_b_results, probs_team_b) team_a_win_prob = probs_team_a.mean()/(probs_team_a.mean()+probs_team_b.mean()) team_b_win_prob = probs_team_b.mean()/(probs_team_a.mean()+probs_team_b.mean()) outcome.append(team_a_win_prob)
循环执行部分
Season = [] ATeam = [] BTeam = [] for index, row in SampleSubmissionWarmup_df.iterrows(): Season = SampleSubmissionWarmup_df.Season ATeam = SampleSubmissionWarmup_df.ATeam BTeam = SampleSubmissionWarmup_df.BTeam get_matchup(row['ATeam'],row['BTeam'],row['Season'])
需求是对每行的两支球队调用机器学习模型计算对战获胜概率,将结果存入列表后添加至DataFrame导出,但执行中出现上述报错,同时需要代码优化建议。
错误原因分析
报错index 1 is out of bounds for axis 1 with size 0本质是:
- 当某行的
(TeamID, Season)组合在df中没有匹配数据时,team_a_stats或team_b_stats会变成空DataFrame - 空DataFrame传入
predict_proba后,模型返回的结果数组维度为(0, n_classes)或直接为空,此时执行[:,1]索引就会触发越界错误
修复方案
在自定义函数中添加空值判断,处理无匹配数据的情况:
outcome = [] def get_matchup(team_a, team_b, season): # 获取球队A数据并处理 team_a_stats = df.loc[(df.TeamID == team_a) & (df.Season == season)] if team_a_stats.empty: # 无数据时的默认处理,比如赋值0.5或跳过 outcome.append(0.5) return team_a_results = team_a_stats['Result'] team_a_stats = team_a_stats.drop(['Result'], axis=1) # 获取球队B数据并处理 team_b_stats = df.loc[(df.TeamID == team_b) & (df.Season == season)] if team_b_stats.empty: outcome.append(0.5) return team_b_results = team_b_stats['Result'] team_b_stats = team_b_stats.drop(['Result'], axis=1) # 计算概率与损失 probs_team_a = loaded_model.predict_proba(team_a_stats)[:,1] loss_team_a = brier_score_loss(team_a_results, probs_team_a) probs_team_b = loaded_model.predict_proba(team_b_stats)[:,1] loss_team_b = brier_score_loss(team_b_results, probs_team_b) # 计算对战胜率,处理分母为0的情况 mean_a = probs_team_a.mean() mean_b = probs_team_b.mean() team_a_win_prob = mean_a / (mean_a + mean_b) if (mean_a + mean_b) != 0 else 0.5 outcome.append(team_a_win_prob)
代码优化建议
1. 移除循环中的冗余代码
原循环里的Season = SampleSubmissionWarmup_df.Season等三行完全冗余,每次循环都把整个列赋值给变量,毫无作用,直接删除:
for index, row in SampleSubmissionWarmup_df.iterrows(): get_matchup(row['ATeam'], row['BTeam'], row['Season'])
2. 替换iterrows()为apply提升效率
iterrows()遍历40多万行效率极低,改用DataFrame.apply实现向量化操作,同时修改函数让它直接返回结果,无需手动维护列表:
def get_matchup(team_a, team_b, season): team_a_stats = df.loc[(df.TeamID == team_a) & (df.Season == season)] if team_a_stats.empty: return 0.5 team_a_results = team_a_stats['Result'] team_a_stats = team_a_stats.drop(['Result'], axis=1) team_b_stats = df.loc[(df.TeamID == team_b) & (df.Season == season)] if team_b_stats.empty: return 0.5 team_b_results = team_b_stats['Result'] team_b_stats = team_b_stats.drop(['Result'], axis=1) probs_team_a = loaded_model.predict_proba(team_a_stats)[:,1] probs_team_b = loaded_model.predict_proba(team_b_stats)[:,1] mean_a = probs_team_a.mean() mean_b = probs_team_b.mean() return mean_a / (mean_a + mean_b) if (mean_a + mean_b) != 0 else 0.5 # 直接生成结果列 SampleSubmissionWarmup_df['TeamA_Win_Prob'] = SampleSubmissionWarmup_df.apply( lambda row: get_matchup(row['ATeam'], row['BTeam'], row['Season']), axis=1 )
3. 预计算球队赛季统计值,彻底抛弃循环
利用pandas分组聚合和合并操作,完全避免循环,性能提升几个数量级:
# 预计算每个球队每个赛季的平均获胜概率 df['Probs'] = loaded_model.predict_proba(df.drop('Result', axis=1))[:,1] team_season_probs = df.groupby(['TeamID', 'Season'])['Probs'].mean().reset_index() # 合并A队数据 SampleSubmissionWarmup_df = SampleSubmissionWarmup_df.merge( team_season_probs, left_on=['ATeam', 'Season'], right_on=['TeamID', 'Season'], how='left' ).rename(columns={'Probs': 'ATeam_Prob'}).drop('TeamID', axis=1) # 合并B队数据 SampleSubmissionWarmup_df = SampleSubmissionWarmup_df.merge( team_season_probs, left_on=['BTeam', 'Season'], right_on=['TeamID', 'Season'], how='left' ).rename(columns={'Probs': 'BTeam_Prob'}).drop('TeamID', axis=1) # 计算对战胜率,处理空值和分母为0的情况 SampleSubmissionWarmup_df['TeamA_Win_Prob'] = SampleSubmissionWarmup_df.apply( lambda row: row['ATeam_Prob']/(row['ATeam_Prob']+row['BTeam_Prob']) if pd.notna(row['ATeam_Prob']) and pd.notna(row['BTeam_Prob']) and (row['ATeam_Prob']+row['BTeam_Prob']) !=0 else 0.5, axis=1 )
4. 移除冗余变量
原函数中team_a = team_a_input这类赋值完全多余,直接使用参数即可,减少代码复杂度。
内容的提问来源于stack exchange,提问作者WooTeenie
相关产品推荐
相关产品推荐

