我用 Python 可视化分析和预测了 2022 年 FIFA 世界杯

许多人称足球为 "不可预测的游戏",因为一场足球比赛有太多不同的因素可以改变最后的比分。

从某种程度上这是真的.....因此本文仅供学习参考!!
预测一场比赛的最终比分或赢家确实是很难的,但在预测一项比赛的赢家时就不是这样了。在过去的5年中,Bayern Munich赢得了所有的德甲联赛,而Manchester City则赢得了4个首发联赛。其实这些都可以用来预测的。

经过测试,本文建立的模型能成功地预测了在20-21赛季中期的所有英超、西甲、意甲和德甲这些联赛的冠军,这也是基于当时已经有近19场比赛了。同样,我们使用该模型来预测下2022年世界杯,会不会有如此惊人的效果呢?一起拭目以待吧~

如何预测比赛呢?

有不同的方法来进行预测。我可以建立一个花哨的机器学习模型并给它提供多个变量,但在阅读了一些论文后,我决定

使用泊松分布试一试。

泊松分布 有读者会疑问,这是为什么呢?那接下来首先看一下泊松分布的定义。

泊松分布

有读者会疑问,这是为什么呢?那接下来首先看一下泊松分布的定义。

泊松分布是一个离散的概率分布,描述了在一个固定的时间间隔或机会区域内发生的事件的数量。

如果我们把进球看作是一场足球比赛90分钟内可能发生的事件,我们可以计算出A队和B队在一场比赛中可能进球的概

率。

但这还不够。我们仍然需要满足泊松分布的假设。

·可以计算事件的数量(一场比赛可以有1、2、3或更多的进球)。

·事件的发生是独立的(一个目标的发生不应影响另一个目标的概率)。

·事件发生的速度是恒定的(在某一时间间隔内发生目标的概率对于相同长度的其他每一个时间间隔都应该是完全相同

的)。

·两个事件不可能在完全相同的时间内发生(两个目标不可能同时发生)

毫无疑问,假设1和4是符合的,但2和3是部分正确的。也就是说,我们假设假设2和3总是正确的。

当预测欧洲顶级联赛的冠军时,我绘制了过去5年前4个联赛每场比赛的进球数柱状图。

2.png

如果你看一下任何联赛的拟合曲线,它看起来像泊松分布。


现在我们可以说,可以用泊松分布来计算一场比赛中可能出现的进球数的概率。

下面是泊松分布的公式。
2.png

为了进行预测,我考虑了。

·lambda:90分钟内进球数的中位数(A队和B队)。

·x:一场比赛中A队和B队可能进的球数

为了计算lambda,我们需要每个国家队的平均进/丢球数。这将我们引向下一个问题。

每个国家队的进球/丢球情况

数据清洗

读取数据

df_historical_data = pd.read_csv('data/fifa_worldcup_matches.csv')

df_fixture = pd.read_csv('data/fifa_worldcup_fixture.csv')

df_missing_data = pd.read_csv('data/fifa_worldcup_missing_data.csv')

 清洗df_fixture

df_fixture['home'] = df_fixture['home'].str.strip()

df_fixture['away'] = df_fixture['away'].str.strip()

 清洗df_missing_data

df_missing_data.dropna(inplace=True)

df_historical_data = pd.concat([df_historical_data, df_missing_data], ignore_index=True)

df_historical_data.drop_duplicates(inplace=True)

df_historical_data.sort_values('year', inplace=True)

df_historical_data


2.png

保存清洗过后的数据

df_historical_data.to_csv('clean_fifa_worldcup_matches.csv',index=False)

df_fixture.to_csv('clean_fifa_worldcup_fixture.csv',index=False)

数据可视化

# nation_position, club_position, player_positions

df = pd.read_csv('players_22.csv', low_memory=False)

# 选择需要用的列

df = df[['short_name', 'age', 'nationality_name', 'overall', 'potential',

'club_name', 'value_eur', 'wage_eur', 'player_positions']]

# 只选择一个position

df['player_positions'] = df['player_positions'].str.split(',', expand=True)[0]

# 删除缺失值

df.dropna(inplace=True)

players_missing_worldcup = ['K. Benzema', 'S. Mané', 'S. Agüero', 'Sergio Ramos',

'P. Pogba', 'M. Reus', 'Diogo Jota', 'A. Harit',

'N. Kanté', 'G. Lo Celso', 'Piqué']

# 删除受伤的球员

drop_index = df[df['short_name'].isin(players_missing_worldcup)].index

df.drop(drop_index, axis=0, inplace=True)

teams_worldcup = [

'Qatar', 'Brazil', 'Belgium', 'France', 'Argentina', 'England', 'Spain', 'Portugal',

'Mexico', 'Netherlands', 'Denmark', 'Germany', 'Uruguay', 'Switzerland', 'United States', 'Croatia',

'Senegal', 'Iran', 'Japan', 'Morocco', 'Serbia', 'Poland', 'South Korea', 'Tunisia',

'Cameroon', 'Canada', 'Ecuador', 'Saudi Arabia', 'Ghana', 'Wales', 'Costa Rica', 'Australia'

]

# 筛选国家队

df = df[df['nationality_name'].isin(teams_worldcup)]

# 最佳球员

df.sort_values(by=['overall', 'potential', 'value_eur'], ascending=False, inplace=True)

 球员分布

球员分布

import numpy as np

fig, ax = plt.subplots(figsize=(12, 5), tight_layout=True)

sns.histplot(df, x='overall', binwidth=1)

bins = np.arange(df['overall'].min(), df['overall'].max(), 1)

plt.xticks(bins)

plt.show()


世界杯梦之队球员

df.drop_duplicates('player_positions')

2.png

每个国家队中最有技能的球员

df_best_players = df.copy()

df_best_players = df_best_players.drop_duplicates('nationality_name').reset_index(drop=True)

country_short =df_best_players['nationality_name'].str.extract('(^\w{3})', expand=False).str.upper()

df_best_players['name_nationality'] = df_best_players['short_name'] +' (' + country_short + ')'

fig, ax = plt.subplots(figsize=(10, 6), tight_layout=True)

sns.barplot(df_best_players, x='overall', y='name_nationality',

palette=sns.color_palette('pastel'), width=0.5)

plt.show()

2.png

 每支球队的最佳阵容
def best_squad(nationality):
df_best_squad = df.copy()
df_best_squad = df_best_squad.groupby(['nationality_name', 'player_positions']).head(2)
df_best_squad = df_best_squad[df_best_squad['nationality_name']==nationality].sort_values(['player_positions', 'overall', 'potential'], ascending=False)
return df_best_squad
best_squad('Brazil')
2.png

average_overall = [best_squad(team)['overall'].mean() for team in teams_worldcup]
df_average_overall = pd.DataFrame({'Teams': teams_worldcup, 'AVG_Overall': average_overall})
df_average_overall = df_average_overall.dropna()
df_average_overall = df_average_overall.sort_values('AVG_Overall', ascending=False)
df_average_overall


2.png

fig, ax = plt.subplots(figsize=(12, 5), tight_layout=True)
sns.barplot(df_average_overall[:10], x='Teams', y='AVG_Overall',
palette=sns.color_palette('pastel'))
plt.show()


2.png


文章为作者独立观点,不代表BOSS直聘立场。未经账号授权,禁止随意转载。