2018年,世界杯小组赛已经在如火如荼的进行中。在上篇文章的基础上【2018世界杯:用Python分析热门夺冠球队】,我们继续分析世界杯32强的实力情况,以期能够更进一步分析本次世界杯的夺冠热门球队。

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

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

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

赌球有风险,看球须尽兴

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

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

本次的环境为

  • window 7 系统
  • python 3.6
  • Jupyter Notebook
  • pandas version 0.22.0

先来看看数据的情况:

import pandas as pd
import matplotlib.pyplot as plt %matplotlib inline
plt.style.use('ggplot') # 解决matplotlib显示中文问题
plt.rcParams['font.sans-serif'] = ['SimHei'] # 指定默认字体
plt.rcParams['axes.unicode_minus'] = False # 解决保存图像是负号'-'显示为方块的问题 df = pd.read_csv('results.csv')
df.head()

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

  • 日期
  • 主队名称
  • 客队名称
  • 主队进球数 (不含点球)
  • 客队进球数 (不含点球)
  • 比赛的类型
  • 比赛所在城市
  • 比赛所在国家
  • 是否中立

结果如下:

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

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

mask = df['home_score'] - df['away_score']
df.loc[mask > 0, 'win_team'] = df.loc[mask > 0, 'home_team']
df.loc[mask < 0, 'win_team'] = df.loc[mask < 0, 'away_team']
df.loc[mask == 0, 'win_team'] = 'Draw' df_FIFA_all = df[df['tournament'].str.contains('FIFA', regex=True)]

结果如下:

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

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

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

team_top5 = ['Germany', 'Argentina', 'Brazil', 'France', 'Spain']
df_FIFA_top5 = df_FIFA_all[(df_FIFA_all['home_team'].isin(team_top5))&
(df_FIFA_all['away_team'].isin(team_top5))]
df_FIFA_top5.shape out:
(43, 10)

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

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

s_FIFA_top5 = df_FIFA_top5.groupby('win_team')['win_team'].count()
s_FIFA_top5.drop('Draw', inplace=True)
s_FIFA_top5.sort_values(ascending=False, inplace=True)
s_FIFA_top5.plot(kind='bar', figsize=(10,6), title='Top Five in World Cup')

结果如下:

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

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

# 自定义函数,返回两支球队获胜场数情况
def team_vs(df,team_A,team_B):
df_team_A_B = df[(df['home_team'].isin([team_A,team_B]))&
(df['away_team'].isin([team_A,team_B]))]
s_win_team = df_team_A_B.groupby('win_team')['win_team'].count()
return s_win_team # 如需获取本文源代码,请关注公众号“Python数据之道”,
# 在公众号后台回复 “code” ,谢谢大家支持。 # 自定义函数,两支球队在世界杯的对阵胜负情况制图
def team_vs_plot(df,team_A,team_B,ax):
s_win_FIFA = team_vs(df,team_A,team_B)
title = team_A + ' vs ' +team_B
s_win_FIFA.plot(kind='bar', ax =ax)
ax.set_xlabel('')
ax.set_title(title,fontdict={'fontsize':10})
ax.set_xticklabels(s_win_FIFA.index, rotation=20)

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

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

f, axes = plt.subplots(figsize=(10,10), ncols=2, nrows=2)
ax1, ax2,ax3,ax4 = axes.ravel()
team_vs_plot(df_FIFA_all,'Brazil','Germany',ax=ax1)
team_vs_plot(df_FIFA_all,'Brazil','Argentina',ax=ax2)
team_vs_plot(df_FIFA_all,'Brazil','France',ax=ax3)
team_vs_plot(df_FIFA_all,'Brazil','Spain',ax=ax4) # 如需获取本文源代码,请关注公众号“Python数据之道”,
# 在公众号后台回复 “code” ,谢谢大家支持。 # set main title of the figure
plt.suptitle('Brazil vs other Top 4 teams in World Cup', fontsize=14, fontweight='bold', x=0.5, y=0.94)
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年以来所有球队所有比赛胜负情况概览

df['date'] = pd.to_datetime(df['date'])
df['year'] = df['date'].dt.year
df_since_2014 = df[df['year']>=2014]
df_since_2014.shape

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

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

s_all = df_since_2014.groupby('win_team')['win_team'].count()
s_all.drop('Draw', inplace=True)
s_all.sort_values(ascending=True, inplace=True)
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强相互之间在所有比赛中的概览情况

team_list = ['Russia', 'Germany', 'Brazil', 'Portugal', 'Argentina', 'Belgium', 'Poland', 'France',
'Spain', 'Peru', 'Switzerland', 'England', 'Colombia', 'Mexico', 'Uruguay', 'Croatia',
'Denmark', 'Iceland', 'Costa Rica', 'Sweden', 'Tunisia', 'Egypt', 'Senegal', 'Iran',
'Serbia', 'Nigeria', 'Australia', 'Japan', 'Morocco', 'Panama', 'Korea Republic', 'Saudi Arabia'] df_top32 = df_since_2014[(df_since_2014['home_team'].isin(team_list))&(df_since_2014['away_team'].isin(team_list))] s_top32 = df_top32.groupby('win_team')['win_team'].count()
s_top32.drop('Draw', inplace=True)
s_top32.sort_values(ascending=True, inplace=True)
s_top32.plot(kind='barh', figsize=(8,12), tick_label='',title='Top 32 in all tournament since 2014')
# plt.ylabel('')

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

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

team_top9 = [ 'Brazil', 'France', 'Portugal',
'Argentina','Mexico','Belgium',
'Germany','Spain','England']
df_top9 = df_since_2014[(df_since_2014['home_team'].isin(team_top9))&
(df_since_2014['away_team'].isin(team_top9))]
df_top9.shape

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

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

九强排名如下:

s_top9 = df_top9.groupby('win_team')['win_team'].count()
s_top9.drop('Draw', inplace=True)
s_top9.sort_values(ascending=False, inplace=True)
s_top9.plot(kind='bar', figsize=(10,6), title='Top 9 in all tournament since 2014')

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

s_tournament = df_top9.groupby('tournament')['tournament'].count()
s_tournament_percentage = s_tournament/s_tournament.sum()
# s_tournament_percentage.sort_values(ascending=False, inplace=True)
s_tournament_percentage.tail(20).plot(kind='pie', figsize=(10,10), autopct='%.1f%%',
startangle=150, title='percentage of tournament', label='',
labeldistance=1.25, pctdistance=1.08)

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

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

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

df_top9_no_friendly = df_top9[df_top9['tournament']!= 'Friendly']
df_top9_no_friendly.groupby('tournament')['tournament'].count() out:
tournament
Confederations Cup 3
FIFA World Cup 6
FIFA World Cup qualification 2
UEFA Euro 2
Name: tournament, dtype: int64

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

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

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

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

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

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

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

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

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

# 自定义获取球队某年至今获胜比例函数
def probability(df,year,team_A,team_B):
prob = []
df_year = df[df['year']>= year]
s = team_vs(df_year,team_A,team_B)
s_team_A = 0 if s.get(team_A) is None else s.get(team_A)
s_A_win = s_team_A/s.sum()
s_team_B = 0 if s.get(team_B) is None else s.get(team_B)
s_B_win = s_team_B/s.sum()
s_draw = 1 - s_A_win - s_B_win
prob.append(year)
prob.append(s_A_win)
prob.append(s_B_win)
prob.append(s_draw)
return prob

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

# 自定义获取两支球队历史获胜情况对比函数
def his_team_data(df,year_start,year_end,team_A,team_B):
row_team = []
# df_team = pd.DataFrame(columns=('year', 'team_A_win', 'team_B_win', 'draw'))
for yr in list(range(year_start,year_end+1)):
team_A_vs_team_B = probability(df,yr,team_A,team_B)
row_team.append(team_A_vs_team_B)
team_A_win = team_A + '_win_percentage'
team_B_win = team_B + '_win_percentage'
df_team = pd.DataFrame(row_team, columns=('year', team_A_win, team_B_win, 'draw_percentage'))
return df_team

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

# 自定义两支球队历史获胜情况制图函数
def team_plot(df,year_start,year_end,team_A,team_B,ax):
team_A_vs_team_B = team_A + '_vs_' + team_B
team_A_vs_team_B = his_team_data(df,year_start,year_end,team_A,team_B)
title = team_A + ' vs ' + team_B
columns = [team_A+'_win_percentage',team_B+'_win_percentage','draw_percentage']
team_A_vs_team_B.set_index('year')[columns].plot(kind='line',figsize=(10,6), title=title,ax=ax)

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

team_A = 'Brazil'
team_B = 'Germany' f, axes = plt.subplots(figsize=(6,12), ncols=1, nrows=2)
ax1, ax2 = axes.ravel() team_plot(df,1930,2016,team_A,team_B,ax1)
ax1.set_xlabel('')
team_plot(df,2000,2016,team_A,team_B,ax2)
ax2.set_title('') plt.show()

上述图中,x轴代表的含义是从某年至今(数据集含有部分2018年的比赛数据),两支球队的胜负情况。
例如 2012对应的是 德国跟巴西从2012年至今,两支球队的胜负情况。

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

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

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

team_A = 'Germany'

for team in ['France','Portugal', 'Argentina','Mexico','Belgium','Brazil','Spain','England']:
team_B = team f, axes = plt.subplots(figsize=(6,12), ncols=1, nrows=2)
ax1, ax2 = axes.ravel() team_plot(df,1930,2016,team_A,team_B,ax1)
ax1.set_xlabel('')
team_plot(df,2000,2016,team_A,team_B,ax2)
ax2.set_title('') plt.show()

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

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


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

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

4 预测

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

  • 意大利,荷兰,连小组赛都没进;
  • 阿根廷,可以说现在已凉了半截;
  • 德国队,若不是最后的绝杀,也差不过可以送首凉凉了,不过现在看已回血大半。

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

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

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

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

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

本文是一次比较综合的项目实战,希望可以给大家带来一些启发。如需获取源代码,请在微信公众号【Python数据之道】后台回复“code”获取。

第二波分析:德国是2018世界杯夺冠最大热门? Python数据分析来揭开神秘面纱… (附源代码)的更多相关文章

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

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

  2. Java设计模式-代理模式之动态代理(附源代码分析)

    Java设计模式-代理模式之动态代理(附源代码分析) 动态代理概念及类图 上一篇中介绍了静态代理,动态代理跟静态代理一个最大的差别就是:动态代理是在执行时刻动态的创建出代理类及其对象. 上篇中的静态代 ...

  3. 世界杯:用Python分析热门夺冠球队-(附源代码)

    2018年,火热的世界杯即将拉开序幕.在比赛开始之前,我们不妨用 Python 来对参赛队伍的实力情况进行分析,并大胆的预测下本届世界杯的夺冠热门球队. 通过数据分析,可以发现很多有趣的结果,比如: ...

  4. EDG夺冠!用Python分析22.3万条数据:粉丝都疯了!

    一.EDG夺冠信息 11月6日,在英雄联盟总决赛中,EDG战队以3:2战胜韩国队,获得2021年英雄联盟全球总决赛冠军,这个比赛在全网各大平台也是备受瞩目: 1.微博热搜第一名,截止2021-11-1 ...

  5. 电商打折套路分析 —— Python数据分析练习

    电商打折套路分析 ——2016天猫双十一美妆数据分析 数据简介 此次分析的数据来自于城市数据团对2016年双11天猫数据的采集和整理,原始数据为.xlsx格式 包括update_time/id/tit ...

  6. 基于binlog来分析mysql的行记录修改情况(python脚本分析)

          最近写完mysql flashback,突然发现还有有这种使用场景:有些情况下,可能会统计在某个时间段内,MySQL修改了多少数据量?发生了多少事务?主要是哪些表格发生变动?变动的数量是怎 ...

  7. 精彩源于起点——2018年潍坊市首次青少年Python编程公开课

    有一种语言叫计算机语言 I want to talk with Computer 春遇到冬,有了岁月 天遇到地,有了永恒 我们拥有的, 不止是长大, 还有那份长大的悲欢经历. 未来会有很多可能, 但一 ...

  8. 【Python 数据分析】从Mysql数据库取出数据作图分析

    在之前的文章中[爬取天气信息]我们已经将昆明二月份的气温爬取到数据库了,那么现在我们需要对这些数据进行一些分析操作,下面是使用matplotlib对这些数据的一些操作 折线图 首先我们读取数据库中的数 ...

  9. 2018超详细sublime text3+python3.x安装配置教程(附常用插件安装教程)

    导读 本文是关于2018年7月最新版sublime text3+pythin3.x下载及安装配置教程,sublime text3版本为3176,python版本为3.7,安装环境是基于windows1 ...

随机推荐

  1. soj1090.Highways

    1090. Highways Constraints Time Limit: 1 secs, Memory Limit: 32 MB Description The island nation of ...

  2. 自己写的一个小的剪刀——石头——布游戏的GUI程序

    很简单的一个程序,建议各位初学Java的同学可以试试写写这个程序: import javax.swing.JOptionPane; public class Game { public static ...

  3. Donald Ervin Knuth:最年轻的图灵奖高德纳

    高德纳(Donald Ervin Knuth,1938年),美国著名计算机科学家,斯坦福大学电脑系荣誉教授.高德纳教授被誉为现代计算机科学的鼻祖,在计算机科学及数学领域发表了多部 具广泛影响的论文和著 ...

  4. CF 1008C Reorder the Array

    You are given an array of integers. Vasya can permute (change order) its integers. He wants to do it ...

  5. 2019年湖南多校第一场||2018-2019 ACM-ICPC Nordic Collegiate Programming Contest (NCPC 2018)

    第一场多校就打的这么惨,只能说自己太菜了,还需继续努力啊- 题目链接: GYM链接:https://codeforces.com/gym/101933 CSU链接:http://acm.csu.edu ...

  6. Django 创建第一个Project — Django学习(二)

    检查django If Django is installed, you should see the version of your installation. If it isn’t, you’l ...

  7. HDU 6215 2017Brute Force Sorting 青岛网络赛 队列加链表模拟

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6215 题意:给你长度为n的数组,定义已经排列过的串为:相邻两项a[i],a[i+1],满足a[i]&l ...

  8. InfluxDB系列之一安装及简单运维(未完成,需要继续写)

    InfluxDB 是一个开源分布式时序.事件和指标数据库.使用 Go 语言编写,无需外部依赖.其设计目标是实现分布式和水平伸缩扩展. 它有三大特性: 1. Time Series (时间序列):你可以 ...

  9. URIEncoding与useBodyEncodingForURI 在tomcat中文乱码处理上的区别

    大家知道tomcat5.0开始,对网页的中文字符的post或者get,经常会出现乱码现象. 具体是因为Tomcat默认是按ISO-8859-1进行URL解码,ISO-8859-1并未包括中文字符,这样 ...

  10. shell 数组基础->

    数组其实也算是变量, 传统的变量只能存储一个值, 但数组可以存储多个值. 普通数组:只能使用整数 作为数组索引 [有序 0 1 2 3 4 ]关联数组:可以使用字符串 作为数组索引 [无序 name ...