Python ValueError形状不匹配问题修复及代码解析
解决ValueError:球队进球/失球统计代码的问题
首先,咱们来拆解你遇到的错误:
ValueError: Shape of passed values is (20, 32), indices imply (20, 38)
这个错误的核心是数据长度不匹配:你创建DataFrame时,传入的每支球队的进球/失球列表长度是32,但代码硬指定了38个索引(对应1到38轮比赛),两者无法对齐,所以抛出了这个错误。
先给你解释原代码的逻辑
get_goals_scored 函数(获取累计进球)
- 初始化球队字典:通过分组主场球队,创建以球队名为键的空字典,用来存储每轮的进球数
- 遍历比赛数据:对每一场比赛,把主场球队的当场进球(
FTHG,Full Time Home Goals)加到对应球队的列表,客场球队的当场进球(FTAG,Full Time Away Goals)也加到对应列表 - 创建累计进球DataFrame:硬编码了1到38轮的索引,转置后行是球队、列是比赛周;然后添加初始值0的列,通过循环累加得到截至每一轮的总进球数
get_goals_conceded 函数(获取累计失球)
逻辑和进球统计几乎一致,只是统计的是失球:
- 主场球队的失球 = 客场球队的进球(
FTAG) - 客场球队的失球 = 主场球队的进球(
FTHG)
错误原因 & 修复方案
错误根源
原代码默认联赛是38轮(比如英超),但你的数据源playing_stat里,每支球队实际只打了32场比赛(可能是赛季未结束、数据只截取了部分轮次),硬编码的38轮索引和实际数据长度不匹配,导致报错。
修复后的代码(动态适配数据长度)
我们把硬编码的38改成动态获取实际比赛轮次,同时优化了球队获取逻辑(避免遗漏球队):
累计进球函数
import pandas as pd def get_goals_scored(playing_stat): # 初始化球队字典:获取所有出现过的球队(主场+客场) teams = {team: [] for team in pd.concat([playing_stat['HomeTeam'], playing_stat['AwayTeam']]).unique()} # 遍历每场比赛,记录各队当场进球 for _, row in playing_stat.iterrows(): home_team = row['HomeTeam'] away_team = row['AwayTeam'] home_goals = row['FTHG'] away_goals = row['FTAG'] teams[home_team].append(home_goals) teams[away_team].append(away_goals) # 动态获取实际比赛轮次(取任意一支球队的比赛场次) num_matchweeks = len(next(iter(teams.values()))) # 创建DataFrame,索引对应实际轮次 goals_scored = pd.DataFrame(data=teams, index=range(1, num_matchweeks + 1)).T # 添加初始累计列(0轮时进球为0) goals_scored[0] = 0 # 按列排序,确保轮次顺序正确 goals_scored = goals_scored.sort_index(axis=1) # 计算截至每一轮的累计进球 for week in range(1, num_matchweeks + 1): goals_scored[week] = goals_scored[week] + goals_scored[week - 1] return goals_scored
累计失球函数
def get_goals_conceded(playing_stat): # 初始化球队字典:获取所有出现过的球队(主场+客场) teams = {team: [] for team in pd.concat([playing_stat['HomeTeam'], playing_stat['AwayTeam']]).unique()} # 遍历每场比赛,记录各队当场失球 for _, row in playing_stat.iterrows(): home_team = row['HomeTeam'] away_team = row['AwayTeam'] # 主场失球=客场进球,客场失球=主场进球 home_conceded = row['FTAG'] away_conceded = row['FTHG'] teams[home_team].append(home_conceded) teams[away_team].append(away_conceded) # 动态获取实际比赛轮次 num_matchweeks = len(next(iter(teams.values()))) goals_conceded = pd.DataFrame(data=teams, index=range(1, num_matchweeks + 1)).T # 添加初始累计列(0轮时失球为0) goals_conceded[0] = 0 goals_conceded = goals_conceded.sort_index(axis=1) # 计算截至每一轮的累计失球 for week in range(1, num_matchweeks + 1): goals_conceded[week] = goals_conceded[week] + goals_conceded[week - 1] return goals_conceded
关键修改点
- 动态获取轮次:不再硬写38,而是从球队的比赛列表长度中获取实际轮次,适配任何长度的数据源
- 更严谨的球队获取:用
concat获取所有主场+客场球队,避免遗漏只出现在客场的球队(虽然联赛中很少见,但更鲁棒) - 用
iterrows()遍历:比原代码的iloc[i]更易读,也更符合pandas的常规写法 - 列排序:确保轮次从0到实际最大轮次的顺序正确,避免累加时出错
内容的提问来源于stack exchange,提问作者cobysim
相关产品推荐
相关产品推荐

