足球作为一项全球性的运动,其不可预测性是其魅力所在。球迷们在比赛前总是热衷于讨论谁会赢得比赛,甚至有人预测比赛的比分。本文将尝试逻辑性地回答这些问题。
足球比赛的不可预测性意味着进球可能在任何时刻发生,与之前的比赛、球队或其他因素无关。这里提到的“随机”事件,实际上可以通过统计学中的泊松分布来计算其发生的概率。泊松分布帮助找到在固定时间段内观察到‘n’个事件(这里指进球)的概率,前提是知道事件平均发生的次数(每个时间段的平均事件数)。
为了回答这些问题,首先需要数据。下载了从1872年到2020年的国际足球比赛结果数据,并创建了一个数据集,计算了每场比赛的总进球数,然后计算了平均进球数。以下是Python代码示例:
import pandas as pd
data = pd.read_csv('data.csv')
print('前5行数据:')
print(data.head())
data['总进球数'] = data['主队进球'] + data['客队进球']
data['年份'] = data['日期'].apply(lambda x : int(str.split(x,'-')[0]))
recent_data = data.loc[(data['年份'] >= 2000)]
recent_data.iloc[[recent_data.总进球数.argmax()]]
print('总进球数平均值:')
print(recent_data.总进球数.mean())
现在,将这个期望值放入泊松分布公式中,看看实际看到一场比赛中进3球的概率是多少。结果只有22%。可以通过绘制进球数的概率图来获得更直观的了解。
假设有一个不耐烦的朋友,他不想看完整场比赛。他在比赛中间问,他需要等待多长时间才能看到进球。这是一个棘手的问题,但不用担心,可以模拟10000场比赛,计算进球之间的平均时间。
最可能的等待时间是2分钟。但这并不是真正想要的,想要知道的是,如果在随机时间开始观看比赛,需要等待的平均时间。为此,将模拟10000个实例,每个实例观看10000场比赛,并报告平均进球等待时间。最后,将绘制这10000个报告,以找出预期的平均等待时间。
看起来大约需要等待33分钟。然而,可能需要等待更长时间,这是一个经典的等待时间悖论。
最后,让回到开始的问题,也是最令人兴奋的问题:谁会赢,确切的比分会是多少。为此,将使用两支球队之间的历史数据(假设为主队和客队),并计算平均主队进球数作为主队预期进球数,平均客队进球数作为客队预期进球数,并使用泊松分布来预测比分。如果两支球队之间的交锋较少,将考虑一些因素:
HS = 主队历史上的平均进球数
AS = 客队历史上的平均进球数
HC = 主队在主场比赛中平均失球数
AC = 客队在客场比赛中平均失球数
主队预期进球数 = (HS + AC) / 2
客队预期进球数 = (AS + HC) / 2
def PredictScore():
home_team = input("请输入主队名称: ")
ht = (''.join(home_team.split())).lower()
away_team = input("请输入客队名称: ")
at = (''.join(away_team.split())).lower()
if len(data[(data.home_team == ht) & (data.away_team == at)]) > 20:
avg_home_score = data[(data.home_team == ht) & (data.away_team == at)].home_score.mean()
avg_away_score = data[(data.home_team == ht) & (data.away_team == at)].away_score.mean()
home_goal = int(stats.mode(np.random.poisson(avg_home_score, 100000))[0])
away_goal = int(stats.mode(np.random.poisson(avg_away_score, 100000))[0])
else:
avg_home_goal_conceded = data[(data.home_team == ht)].away_score.mean()
avg_away_goal_scored = data[(data.away_team == at)].away_score.mean()
away_goal = int(stats.mode(np.random.poisson(1/2 * (avg_home_goal_conceded + avg_away_goal_scored), 100000))[0])
avg_away_goal_conceded = data[(data.home_team == at)].home_score.mean()
avg_home_goal_scored = data[(data.away_team == ht)].home_score.mean()
home_goal = int(stats.mode(np.random.poisson(1/2 * (avg_away_goal_conceded + avg_home_goal_scored), 100000))[0])
avg_total_score = int(stats.mode(
np.random.poisson((data[(data.home_team == ht) & (data.away_team == at)].total_goals.mean()), 100000))[0])
print(f'预期总进球数为 {avg_total_score}')
print(f'他们共进行了 {len(data[(data.home_team == ht) & (data.away_team == at)])} 场比赛')
print(f'预测比分为 {home_team} {home_goal} : {away_goal} {away_team}')
PredictScore()