点击上方“程序人生”,选择“置顶公众号”

第一时间关注程序猿(媛)身边的故事

图片源自网络

作者

Lemon

如需转载,请联系原作者授权。

三十年河东三十年河西,对于世界杯而言,这个时间可能4年就足够。

前几场爆冷,使得天台上已经拥挤不堪,跳水的股市更是让天台一度混乱。

在文章开始之前,提醒大家:

赌球有风险,看球须尽兴

本文的重点是通过分析32强之间的比赛,透过历史数据来预测夺冠热门球队。

本次分析的数据来源于 Kaggle, 包含从 1872 年到今年的数据,包括世界杯比赛、世界杯预选赛、亚洲杯、欧洲杯、国家之间的友谊赛等比赛,一共大约 40000 场比赛的情况。

本次的环境为

  • window 7 系统

  • python 3.6

  • Jupyter Notebook

  • pandas version 0.22.0

先来看看数据的情况:

  1. import pandas as pd

  2. import matplotlib.pyplot as plt

  3. %matplotlib inline

  4. plt.style.use('ggplot')

  5. # 解决matplotlib显示中文问题

  6. plt.rcParams['font.sans-serif'] = ['SimHei']  # 指定默认字体

  7. plt.rcParams['axes.unicode_minus'] = False  # 解决保存图像是负号'-'显示为方块的问题

  8. df = pd.read_csv('results.csv')

  9. df.head()

该数据集包含的数据列的信息如下:

  • 日期

  • 主队名称

  • 客队名称

  • 主队进球数 (不含点球)

  • 客队进球数 (不含点球)

  • 比赛的类型

  • 比赛所在城市

  • 比赛所在国家

  • 是否中立

结果如下:

1、 获取所有世界杯比赛的数据(含预选赛)

创建一个新的列数据,包含获胜队伍的信息,以及获取所有世界杯比赛的数据,包含预选赛。

  1. mask = df['home_score'] - df['away_score']

  2. df.loc[mask > 0, 'win_team'] = df.loc[mask > 0, 'home_team']

  3. df.loc[mask < 0, 'win_team'] = df.loc[mask < 0, 'away_team']

  4. df.loc[mask == 0, 'win_team'] = 'Draw'

  5. df_FIFA_all = df[df['tournament'].str.contains('FIFA', regex=True)]

结果如下:

2、 世界杯战绩分析 (含预选赛)

从前文来看, 在世界杯历史上,实力最强的5支球队是 德国、阿根廷、巴西、法国、西班牙。

接下来,我们将比赛的范围扩大至包含世界杯预选赛,通过5支球队之间的比赛情况来进行分析。

  1. team_top5 = ['Germany', 'Argentina', 'Brazil', 'France', 'Spain']

  2. df_FIFA_top5 = df_FIFA_all[(df_FIFA_all['home_team'].isin(team_top5))&

  3.                                        (df_FIFA_all['away_team'].isin(team_top5))]

  4. df_FIFA_top5.shape

  5. out:

  6. (43, 10)

在世界杯历史上,5支球队在共有43场比赛相遇。

通过这43场比赛分析后,5支球队的胜负场数排名如下:

  1. s_FIFA_top5 = df_FIFA_top5.groupby('win_team')['win_team'].count()

  2. s_FIFA_top5.drop('Draw', inplace=True)

  3. s_FIFA_top5.sort_values(ascending=False, inplace=True)

  4. s_FIFA_top5.plot(kind='bar', figsize=(10,6), title='Top Five in World Cup')

结果如下:

下面,着重来分析下这5支球队,在世界杯上,两两对阵时的胜负情况。

首先自定义两个函数,分别获得两支球队获胜场数情况以及自定义绘图函数

  1. # 自定义函数,返回两支球队获胜场数情况

  2. def team_vs(df,team_A,team_B):

  3.    df_team_A_B = df[(df['home_team'].isin([team_A,team_B]))&

  4.                                        (df['away_team'].isin([team_A,team_B]))]

  5.    s_win_team = df_team_A_B.groupby('win_team')['win_team'].count()

  6.    return s_win_team

  7. # 如需获取本文源代码,请关注公众号“Python数据之道”,

  8. # 在公众号后台回复 “code” ,谢谢大家支持。

  9. # 自定义函数,两支球队在世界杯的对阵胜负情况制图

  10. def team_vs_plot(df,team_A,team_B,ax):

  11.    s_win_FIFA = team_vs(df,team_A,team_B)

  12.    title = team_A + ' vs ' +team_B

  13.    s_win_FIFA.plot(kind='bar', ax =ax)

  14.    ax.set_xlabel('')

  15.    ax.set_title(title,fontdict={'fontsize':10})

  16.    ax.set_xticklabels(s_win_FIFA.index, rotation=20)

基于上述函数,分析结果如下:

2.1 世界杯战绩:巴西 vs 其他4支球队

  1. f, axes = plt.subplots(figsize=(10,10), ncols=2, nrows=2)

  2. ax1, ax2,ax3,ax4 = axes.ravel()

  3. team_vs_plot(df_FIFA_all,'Brazil','Germany',ax=ax1)

  4. team_vs_plot(df_FIFA_all,'Brazil','Argentina',ax=ax2)

  5. team_vs_plot(df_FIFA_all,'Brazil','France',ax=ax3)

  6. team_vs_plot(df_FIFA_all,'Brazil','Spain',ax=ax4)

  7. # 如需获取本文源代码,请关注公众号“Python数据之道”,

  8. # 在公众号后台回复 “code” ,谢谢大家支持。

  9. # set main title of the figure

  10. plt.suptitle('Brazil vs other Top 4 teams in World Cup', fontsize=14, fontweight='bold', x=0.5, y=0.94)

  11. plt.show()

结果如下:

统计现象1:

在世界杯上的战绩,统计获胜场数如下(不含平局):

巴西1:1德国,巴西6:3阿根廷,巴西1:2法国,巴西3:1西班牙

巴西队,输赢不好判断……

2.2 世界杯战绩:德国 vs 其他3支球队

代码跟2.1部分是类似的,结果如下:

统计现象2:

在世界杯上的战绩,统计获胜场数如下(不含平局):

德国4:1阿根廷,德国2:1法国,德国2:1西班牙

德国在这5支球队里,获胜的优势相对比较明显。

2.3 世界杯战绩:阿根廷 vs 其他2支球队

代码跟2.1部分是类似的,结果如下:

统计现象3:

在世界杯上的战绩,统计获胜场数如下(不含平局):

阿根廷2:0法国,阿根廷1:0西班牙

但阿根廷不敌巴西和德国

2.4 世界杯战绩:西班牙 vs 法国

综合小结论:

从历届世界杯上的表现情况来看,分析5强之间两两对阵后,发现德国队的表现是最好的。其次巴西和阿根廷的表现也不错。

考虑到,历届世界杯的数据,时间跨度很大,很多球队其实已经发生了很大变化。

球队真实的情况,可能选择近几年的比赛,以及包含不同级别的比赛,可能分析效果要更好些。

文中有获取本文源代码的方式

下面,重点来分析2014年以来包含所有比赛的情况。

3、2014年以来,所有比赛的战绩对比

首先,时间选择2014年之后(含2014年),距离现在的时间比较近,相对来说,球队人员的组成变化小一些。

当然,这里的时间选择,对于结果是有影响的。 大家可以探讨下这个因素带来的影响。

3.1 2014年以来所有球队所有比赛胜负情况概览

  1. df['date'] = pd.to_datetime(df['date'])

  2. df['year'] = df['date'].dt.year

  3. df_since_2014 = df[df['year']>=2014]

  4. df_since_2014.shape

2014年以来,共有3600多场比赛。

针对3600多场比赛分析后,胜负场数情况如下:

  1. s_all = df_since_2014.groupby('win_team')['win_team'].count()

  2. s_all.drop('Draw', inplace=True)

  3. s_all.sort_values(ascending=True, inplace=True)

  4. s_all.tail(50).plot(kind='barh', figsize=(8,16), tick_label='',title='Top 50 in all tournament since 2014')

从上图来看,2014年以来,墨西哥,法国,德国、葡萄牙、巴西、比利时、韩国和西班牙表现相对较好。

结果是不是跟想象中的有些差异?

6月17日的小组赛,德国不敌墨西哥,看来也不是全无理由的。

但是,本次我们主要还是要考虑32强之间的对阵,这样更能反映现实情况。

3.2 2014年以来32强相互之间在所有比赛中的概览情况

  1. team_list = ['Russia', 'Germany', 'Brazil', 'Portugal', 'Argentina', 'Belgium', 'Poland', 'France',

  2.             'Spain', 'Peru', 'Switzerland', 'England', 'Colombia', 'Mexico', 'Uruguay', 'Croatia',

  3.            'Denmark', 'Iceland', 'Costa Rica', 'Sweden', 'Tunisia', 'Egypt', 'Senegal', 'Iran',

  4.            'Serbia', 'Nigeria', 'Australia', 'Japan', 'Morocco', 'Panama', 'Korea Republic', 'Saudi Arabia']

  5. df_top32 = df_since_2014[(df_since_2014['home_team'].isin(team_list))&(df_since_2014['away_team'].isin(team_list))]

  6. s_top32 = df_top32.groupby('win_team')['win_team'].count()

  7. s_top32.drop('Draw', inplace=True)

  8. s_top32.sort_values(ascending=True, inplace=True)

  9. s_top32.plot(kind='barh', figsize=(8,12), tick_label='',title='Top 32 in all tournament since 2014')

  10. # plt.ylabel('')

从上图来看,自2014年以来,巴西、法国、葡萄牙、阿根廷、墨西哥、比利时、德国、西班牙、英国为前9强

下面我们来分析top9之间的胜负情况。

  1. team_top9 = [ 'Brazil', 'France', 'Portugal',

  2.             'Argentina','Mexico','Belgium',

  3.             'Germany','Spain','England']

  4. df_top9 = df_since_2014[(df_since_2014['home_team'].isin(team_top9))&

  5.                        (df_since_2014['away_team'].isin(team_top9))]

  6. df_top9.shape

2014年以来,top 9 之间一共踢了44场比赛(包括友谊赛)。

总体来说,比赛的场数不是太多,基于这些数据来分析,可能对结果会有较大的影响。

九强排名如下:

  1. s_top9 = df_top9.groupby('win_team')['win_team'].count()

  2. s_top9.drop('Draw', inplace=True)

  3. s_top9.sort_values(ascending=False, inplace=True)

  4. s_top9.plot(kind='bar', figsize=(10,6), title='Top 9 in all tournament since 2014')

来查看下都统计了哪些类型的比赛

  1. s_tournament = df_top9.groupby('tournament')['tournament'].count()

  2. s_tournament_percentage = s_tournament/s_tournament.sum()

  3. # s_tournament_percentage.sort_values(ascending=False, inplace=True)

  4. s_tournament_percentage.tail(20).plot(kind='pie', figsize=(10,10), autopct='%.1f%%',

  5.                           startangle=150, title='percentage of tournament', label='',

  6.                                     labeldistance=1.25, pctdistance=1.08)

从上面来看,友谊赛占的比例较大。

考虑到友谊赛在有些情况下可能不能比较准确的反映出球队的真实水平,且友谊赛站的场数比例较大,我们剔除友谊赛再来看看结果情况。

3.3 2014年以来32强剔除友谊赛后的胜负情况概览

  1. df_top9_no_friendly = df_top9[df_top9['tournament']!= 'Friendly']

  2. df_top9_no_friendly.groupby('tournament')['tournament'].count()

  3. out:

  4. tournament

  5. Confederations Cup              3

  6. FIFA World Cup                  6

  7. FIFA World Cup qualification    2

  8. UEFA Euro                       2

  9. Name: tournament, dtype: int64

剔除友谊赛后,比赛类型分布如下:

剔除友谊赛后,Top 9 的情况如下:

在概览中可以看出,是否剔除友谊赛(Friendly),对排名还是有影响的。

另外,剔除友谊赛后,总的比赛场数更少了(只有13场),9强之间有些队伍没有比赛,或者没有赢过,这个数据用来分析的作用更有限。

当然,在分析中 是否要剔除友谊赛,应该是值得商榷的。

3.4 九强两两对阵的胜负情况概览

这里,我们后续分析采用包含友谊赛的数据,来分别分析9强之间两两对阵的情况,看看哪支球队的胜率更高些。

首先自定义几个函数,方便进行分析。

自定义获取球队某年至今获胜比例函数

  1. # 自定义获取球队某年至今获胜比例函数

  2. def probability(df,year,team_A,team_B):

  3.    prob = []

  4.    df_year = df[df['year']>= year]

  5.    s = team_vs(df_year,team_A,team_B)

  6.    s_team_A = 0 if s.get(team_A) is None else s.get(team_A)

  7.    s_A_win = s_team_A/s.sum()

  8.    s_team_B = 0 if s.get(team_B) is None else s.get(team_B)

  9.    s_B_win = s_team_B/s.sum()

  10.    s_draw = 1 - s_A_win - s_B_win

  11.    prob.append(year)

  12.    prob.append(s_A_win)

  13.    prob.append(s_B_win)

  14.    prob.append(s_draw)

  15.    return prob  

自定义获取两支球队历史获胜情况对比函数

  1. # 自定义获取两支球队历史获胜情况对比函数

  2. def his_team_data(df,year_start,year_end,team_A,team_B):

  3.    row_team = []

  4. #     df_team = pd.DataFrame(columns=('year', 'team_A_win', 'team_B_win', 'draw'))

  5.    for yr in list(range(year_start,year_end+1)):

  6.        team_A_vs_team_B = probability(df,yr,team_A,team_B)

  7.        row_team.append(team_A_vs_team_B)

  8.    team_A_win = team_A + '_win_percentage'

  9.    team_B_win = team_B + '_win_percentage'

  10.    df_team = pd.DataFrame(row_team, columns=('year', team_A_win, team_B_win, 'draw_percentage'))

  11.    return df_team

自定义两支球队历史获胜情况制图函数

  1. # 自定义两支球队历史获胜情况制图函数

  2. def team_plot(df,year_start,year_end,team_A,team_B,ax):

  3.    team_A_vs_team_B = team_A + '_vs_' + team_B

  4.    team_A_vs_team_B = his_team_data(df,year_start,year_end,team_A,team_B)

  5.    title = team_A + ' vs ' + team_B

  6.    columns = [team_A+'_win_percentage',team_B+'_win_percentage','draw_percentage']

  7.    team_A_vs_team_B.set_index('year')[columns].plot(kind='line',figsize=(10,6), title=title,ax=ax)

这些函数有什么用呢,首先我们来分析下 巴西 vs 德国 的情况,如下:

  1. team_A = 'Brazil'

  2. team_B = 'Germany'

  3. f, axes = plt.subplots(figsize=(6,12), ncols=1, nrows=2)

  4. ax1, ax2 = axes.ravel()

  5. team_plot(df,1930,2016,team_A,team_B,ax1)

  6. ax1.set_xlabel('')

  7. team_plot(df,2000,2016,team_A,team_B,ax2)

  8. ax2.set_title('')

  9. plt.show()

上述图中,x轴代表的含义是从某年至今(数据集含有部分2018年的比赛数据),两支球队的胜负情况。

例如 2012对应的是 德国跟巴西从2012年至今,两支球队的胜负情况。

所以,时间越早,两支球队的比赛数量越多,数据曲线的波动可能要小些。但由于球队的成员组成在不断的变化,会导致越早的数据,其分析价值越弱。 因此,选择合适的年份进行分析就显得很重要。

有童鞋说,如果我要 同时分析德国对阵另外8支球队呢?

这里,用上面的函数,也是很迅速的,代码如下:

  1. team_A = 'Germany'

  2. for team in ['France','Portugal', 'Argentina','Mexico','Belgium','Brazil','Spain','England']:

  3.    team_B = team

  4.    f, axes = plt.subplots(figsize=(6,12), ncols=1, nrows=2)

  5.    ax1, ax2 = axes.ravel()

  6.    team_plot(df,1930,2016,team_A,team_B,ax1)

  7.    ax1.set_xlabel('')

  8.    team_plot(df,2000,2016,team_A,team_B,ax2)

  9.    ax2.set_title('')

  10.    plt.show()

运行上述代码后,将会绘制8张图,下面只放上其中几张图。

同理,如果你喜欢巴西队或者别的球队,也可以用上述代码进行分析。

用上述函数可以快速的分析两支球队的历史胜负情况,当然,有些球队之间,相遇很少,或者近些年没有遭遇过,那分析结果可能就不好用了。

当然,数据分析的只是历史情况,足球是圆的,场上瞬息万变。比如,阿根廷现在岌岌可危,梅西内心慌得一逼……

4 预测

本届世界杯真的是爆冷太多。

意大利,荷兰,连小组赛都没进;

阿根廷,可以说现在已凉了半截;

德国队,若不是最后的绝杀,也差不过可以送首凉凉了,不过现在看已回血大半。

最后,来放上我的神预测。

黑马年年有,今年特别多,预测不准,坐等 pia pia 打脸。

当然,其实我内心深处希望是下面这样的。

怎么样,为强大的内心点赞吧~~

特别说明: 以上数据分析,纯属个人学习用,预测结果与实际情况可能偏差很大,不能用于其他用途。

- The End -

「若你有原创文章想与大家分享,欢迎投稿。」

加编辑微信ID,备注#投稿#:

程序 丨 druidlost

小七 丨 duoshangshuang

更多精彩内容

德国是2018世界杯夺冠最大热门? Python数据分析来揭开神秘面纱…相关推荐

  1. EDG夺冠,用Python数据分析一波:粉丝都炸锅了

    EDG夺冠,粉丝炸锅了! 北京时间11月6日,在英雄联盟S11总决赛中,中国LPL赛区战队EDG电子竞技俱乐部以3∶2战胜韩国LCK赛区战队DK,获得2021年英雄联盟全球总决赛冠军. 这个比赛也是备 ...

  2. 开源热门Python数据分析库:Pandas下载和安装以及用途

    Pandas 是一个开源的第三方 Python 库,从 Numpy 和 Matplotlib 的基础上构建而来,享有数据分析"三剑客之一"的盛名(NumPy.Matplotlib. ...

  3. python模拟足球射门_用Python模拟2018世界杯夺冠之路

    2018俄罗斯世界杯小组抽签出炉,几家欢喜几家愁.世界杯从来就不乏看点,东道主俄罗斯能走多远.德国能否卫冕.西班牙是否有望东山再起.两位球王谁更接近大力神杯...距世界杯开幕还有半年时间,一切都是未知 ...

  4. python分析比赛_实战项目练习 ---- 【2018世界杯】用python分析夺冠球队

    2018世界杯 前言 在网上找到了个用Python分析2018世界杯夺冠热门的项目,感觉很有意思准备拿来练练手. 因为目前还没有学到图形可视化部分,所以这部分内容会完全借鉴网上的教程. 分析目的 通过 ...

  5. 2018世界杯球队热度CGI榜:大数据预测巴西、法国成夺冠热门

    2018世界杯赛程已过半,在各种爆冷和黑马横飞之中,球迷们目送卫冕冠军德国队带着几百斤土豆离开了俄罗斯,也为梅西和C罗的离去在天台久久徘徊.在各种实力排行榜都被推翻后,球迷们苦于找不到一个依据来预测今 ...

  6. 2006世界杯夺冠热门分析

    世界杯如同炎炎的夏日,越来越近,越来越热,大家的内心也越来越激动,四年一次,世界杯终于又来了.02年的硝烟还未散尽,06年各路豪强又要捉对厮杀,只为了那一尊大力神杯,那一份至高无上的荣耀.       ...

  7. python 统计组合用什么库_盘点2018年热门Python库|TOP20

    来源:CDA数据分析师 在解决数据科学任务和挑战方面,Python继续处于领先地位.去年,我对当时热门的Python库进行了总结.今年,我在当中加入新的库,重新对2018年热门Python库进行全面盘 ...

  8. 利用世界杯,读懂 Python 装饰器

    Python 装饰器是在面试过程高频被问到的问题,装饰器也是一个非常好用的特性, 熟练掌握装饰器会让你的编程思路更加宽广,程序也更加 pythonic. 今天就结合最近的世界杯带大家理解下装饰器. 德 ...

  9. 利用世界杯,读懂 Python 装饰器 1

    Python 装饰器是在面试过程高频被问到的问题,装饰器也是一个非常好用的特性, 熟练掌握装饰器会让你的编程思路更加宽广,程序也更加 pythonic. 今天就结合最近的世界杯带大家理解下装饰器. 德 ...

  10. 2018世界杯数据清单:真球迷看球必备,伪球迷速成指南(附完整赛程)

    导读:每隔4年都有那么1个月,无论是线上还是线下,不管是真球迷还是真球盲,你的社交圈子都会被世界杯话题攻占.每到这个时候,真球迷一言不合就面红耳赤,伪球迷尬聊不超过3句就暴露"球商" ...

最新文章

  1. 一口气发布1008种机器翻译模型,GitHub最火NLP项目大更新
  2. SAP MM 盘点凭证上的posting block
  3. SAP MM 如何知道移动类型的字段选择和会计科目的字段选择是否不一致?
  4. 高性能的JavaScript--加载和执行
  5. Mysql学习笔记【原创】
  6. asp.net web 开发登录相关操作的控件LoginName、LoginStatus和LoginView控件使用详解
  7. D - Delete Prime Gym - 102875D
  8. 【HDU - 1216 】Assistance Required (模拟,类似素数打表,不是素数问题!)
  9. 踵事增华:新形势下如何高效撰写科技论文!
  10. python的OS库测试
  11. matlab课后答案杨德平,MATLAB基础教程习题答案作者杨德平例题源程序课件.pdf
  12. 2525 小b的字符串 (字符串思维、dp、胡搞都能过)
  13. Java语音转文字功能
  14. .tar.bz2文件怎么解压
  15. 【科普文】一文详解红外遥控模块工作原理
  16. 微信小程序 满意度调查问卷
  17. Intel SGX入门
  18. 从java9共享内存加载modules说起
  19. 编码解码--url编码解码
  20. 电视电脑盒子,一机两用,电视秒变电脑

热门文章

  1. 嵌入式--Flash操作中的标准SPI,Dual SPI,Quad SPI
  2. Golang interface接口深入理解
  3. excel两列数据对比找不同_眼睛的救星,Excel怎么快速找出两列数据的不同之处?...
  4. 两列数据对比找不同,并且高亮数据不同的单元格
  5. 西安电子科技大学计算机水平,“两电一邮”的西安电子科技大学,在国内高校中,到底什么水平?...
  6. 大话西游2人数最多服务器,大话2大话各个服务器狂人榜排名 看大话如今服务器...
  7. 剑三 服务器状态查询,数据互通全面启动_剑侠情缘网络版叁_金山游戏官方网站_金山逍遥Xoyo.com...
  8. 我的团长我的团第二十七集
  9. 48脚STM32内部基准电压校准ADC的一些心得记录
  10. 灵飞经 ①洪武天下 第二章 紫禁深深