数据来源:kaggle数据准备
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import scipy as sp
inpath=r'C:\Users\......\Football\football-events\events.csv'
events=pd.read_csv(inpath) #导入主数据
events.isnull().sum() #缺失值汇总情况
path2=r'C:\Users\......\Football\football-events\dictionary.txt'
encoding=pd.read_table(path2,delim_whitespace=False,names=('num','events')) #导入解释性文件。因为主文件中都是用数字代替类型的
将主文件和解释性文件都导入python中
查看数据基本信息:
event.columns #主文件列名
event.isnull.sum()#汇总缺失值的信息
#提取各解释性文件,源文件为txt格式
event_type=encoding[1:13]
event_type_2=encoding[14:18]
side=encoding[19:21]
shot_place=encoding[22:35]
shot_outcome=encoding[36:40]
location=encoding[41:60]
bodypart=encoding[61:64]
assist_method=encoding[65:70]
situition=encoding[71:75]
将解释性文件保存,取消各解释性文件中的索引
event_type.to_csv(r'C:\Users\......\Football\football-events\event_type1.csv',index=False)
event_type_2.to_csv(r'C:\Users\......\Football\football-events\event_type_2.csv',index=False,header=False)
side.to_csv(r'C:\Users\......\Football\football-events\side.csv',index=False)
shot_place.to_csv(r'C:\Users\......\Football\football-events\shot_place.csv',index=False)
shot_outcome.to_csv(r'C:\Users\......\Football\football-events\shot_outcome.csv',index=False)
location.to_csv(r'C:\Users\......\Football\football-events\location.csv',index=False)
bodypart.to_csv(r'C:\Users\......\Football\football-events\bodypart.csv',index=False)
assist_method.to_csv(r'C:\Users\......\Football\football-events\assist_method.csv',index=False)
situition.to_csv(r'C:\Users\......\Football\football-events\situition.csv',index=False)
到目前为止,对文件的处理工作基本完成。当然,你也可以将解释性文件导入到主文件中,程序如下(各人觉得没必要):
y=[]
def tidai(x):
if x==1:
y='right foot'
if x==2:
y="left foot"
else:
y="head"
return y
goal1['events']=goal['bodypart'].apply(tidai) #将bodypart这个解释性文件内容导入到主文件中
对进球情况进行分析
# 选取有进球的赛事
goal=events[events.is_goal==1]对进球随时间分布情况进行分析
goal.time.max() #可知进球的时间最大为100min,即做直方图时可采用划分100等分
plt.figure(figsize=(20,20)) #设置画布大小
plt.rc("xtick",labelsize=20) #设置x刻度的文字大小
plt.rc("ytick",labelsize=20) #设置y轴刻度文字大小
plt.hist(goal.time,bins=100,color='blue',width=1) #将进球时间作为x轴,bins划分等分,设置颜色以及宽度
plt.xlabel("TIME",fontsize=30) #设置x轴的的文字以及大小
plt.ylabel("goal counts",fontsize=30) #设置y轴的的文字以及大小
plt.title("goal counts vs time",fontsize=35) #设置图标的标题
plt.show()进球数 vs 时间
结论:可以看出,所有赛事中进球的时间分布,其中在90min左右进球最多,其次是45min左右。当然,也可使用程序查看时间
goal.groupby(by=['time'])['is_goal'].sum().sort_values(ascending=False).head()进球最多的时间分布(top5)主客队进球情况分析
通过解释文件side可以知道,主文件中1代表主队,2代表客队
plt.figure(figsize=(20,15))
plt.grid() #开启网格
plt.rc('xtick',labelsize=20)
plt.rc('ytick',labelsize=20)
plt.hist(goal[goal.side==1].time,bins=100,label="Home team",color='green',width=1) #主队进球情况
plt.hist(goal[goal.side==2].time,bins=100,label="Away team",width=1) #客队进球情况
plt.xlabel("Time",fontsize=25)
plt.ylabel("counts",fontsize=25)
plt.title("goal counts vs time by side",fontsize=30)
plt.legend(loc="upper left",fontsize=15) #设置图例文字大小以及位置
plt.show()
结论:主动进球情况明显好于客队,主场作战一般都比较厉害怎么样进球的
goal['bodypart']=goal['bodypart'].fillna(1) #发现goal文件中bodypart还有一个缺失值,因此进行填充
goal['bodypart']=goal['bodypart'].astype('int') #改变数据格式,这条没有用的
goal1=goal.copy()
plt.figure(figsize=(10,10))
labels=["Right Foot","Left Foot","Headers"]
data1=[goal1[goal1["bodypart"]==1].shape[0],goal1[goal1["bodypart"]==2].shape[0],goal1[goal1["bodypart"]==3].shape[0]]
# shape[0]是用来汇总行数,当然这里也可以用groupby
# data1=goal1.groupby(by=['bodypart'])['bodypart'].count()
colors=["cyan","grey","pink"]
plt.pie(data1,labels=labels,colors=colors,autopct='%1.1f%%',startangle=60)
plt.axis('equal')
plt.title("Percentage of bodyparts for goals",fontname="Times New Roman Bold",fontsize=14)
plt.show()
结论:右脚进球是最主要的进攻方式,左脚次之,投球最少
plt.figure(figsize=(15,10))
plt.hist(goal1[goal1["bodypart"]==1]["time"],width=1,bins=100,color="cyan",label="Right foot")
plt.hist(goal1[goal1["bodypart"]==2]["time"],width=1,bins=100,color="grey",label="Left foot")
plt.hist(goal1[goal1["bodypart"]==3]["time"],width=1,bins=100,color="pink",label="Headers")
plt.xlabel("Minutes",fontsize=20)
plt.ylabel("Number of goals",fontsize=20)
plt.legend(loc='upper left')
plt.title("Number of goals (by body parts) against Time during match",fontname="Times New Roman Bold",fontsize=20,fontweight="bold")
plt.show()
可以看出:各种进攻方式随时间变化的趋势在何种情况下进球的分析
plt.figure(figsize=(15,15))
size=[goal1[goal1.situation==1].shape[0],goal1[goal1.situation==2].shape[0],goal1[goal1.situation==3].shape[0],goal1[goal1.situation==4].shape[0]]
colors=['pink','purple','blue','green']
plt.pie(size,colors=colors,labels=list(situition['events']),autopct='%.1f%%',textprops={"fontsize":15})
plt.title('Percentage of each situation for goals',fontsize=25)
plt.axis('equal')
plt.show()
结论:运动战的进球是最多的,占比达到70.8%
plt.figure(figsize=(20,10))
plt.hist(goal1[goal1.situation==1].time,bins=100,width=1,color='pink',label='Open play')
plt.hist(goal1[goal1.situation==2].time,bins=100,width=1,color='purple',label='Set piece')
plt.hist(goal1[goal1.situation==3].time,bins=100,width=1,color='blue',label='Corner')
plt.hist(goal1[goal1.situation==4].time,bins=100,width=1,color='green',label='Free kick')
plt.xlabel("TIME",fontsize=25)
plt.ylabel("goal counts",fontsize=25)
plt.rc('xtick',labelsize=15)
plt.rc('ytick',labelsize=15)
plt.title('Percentage of each situation for goals',fontsize=25,fontweight='bold')
plt.legend(loc='upper left',fontsize=15)
plt.show()
结论:各种进球方式随时间的变化可以看出,运动战中的进球均远远高于其他进球方式在哪进球的分析
将进球的位置划分为5类,但在主文件中尽然划分为15处,因此要进行简单处理
goal1.location.fillna(goal1.location.median(),inplace=True) #对缺失值进行众数的填充
goal1.location.unique() #结果为array([ 9., 3., 13., 15., 10., 11., 19., 6., 7., 14., 12.,8., 17., 18., 16.])
#获取划分为5类的汇总情况
diff_angle_goals=goal1[goal1.location==6].shape[0]+goal1[goal1.location==7].shape[0]+goal1[goal1.location==8].shape[0];
longdistance=goal1[goal1.location==16].shape[0]+goal1[goal1.location==17].shape[0]+goal1[goal1.location==18].shape[0]
box_goal=goal1[goal1.location==3].shape[0]+goal1[goal1.location==9].shape[0]+goal1[goal1.location==11].shape[0]+goal1[goal1.location==15].shape[0]
close_range_goals=sum(goal1["location"]==10)+sum(goal1["location"]==12)+sum(goal1["location"]==13)
penalties=goal1[goal1.location==14].shape[0]
not_recorded=goal1[goal1.location==19].shape[0]
#绘图
data=[diff_angle_goals,longdistance,box_goal,close_range_goals,penalties,not_recorded]; #将数据组成一个list
label=['diff_angle_goals','longdistance','box_goal','close_range_goals','penalties','not_recorded']#图例
colors=["gray","yellow","aqua","coral","red","violet"] #颜色
distance=[0,0.,0.05,0,0.,0] #突出显示最大值
plt.figure(figsize=(15,15))
plt.pie(data,colors=colors,labels=label,autopct='%.2f%%',labeldistance=1,startangle=30,
explode=distance,textprops={'fontsize':13},radius=2)
plt.axis('equal')
plt.title("Percentage of each location for goals",fontsize=18,fontweight="bold")
plt.legend(fontsize=12)
plt.show()
结论:大部分得分都来自禁区(64.55%)和近距离射门(19.43%)助攻分布情况
goal1.groupby(by='assist_method')['time'].count() #各助攻情况的分布情况
list(assist_method.events)
plt.figure(figsize=(10,10))
plt.pie(goal1.groupby(by='assist_method')['time'].count(),labels=list(assist_method.events),autopct='%1.2f%%'
,textprops={'fontsize':15,'color':'black'})
plt.title("assist_method info",fontsize=20)
plt.axis('equal')
plt.show()
结论:超过32%的进球都是独自完成,没有通过助攻形式,35.43%是靠直接助攻而得分
对赛事中替换情况进行分析
有解释文件中可以看出,event_type为7的是有替换值的赛事
substitution=events[events.event_type==7] #获取替换的赛事
plt.figure(figsize=(20,13))
plt.rc('xtick',labelsize=15)
plt.rc('ytick',labelsize=15)
plt.plot(substitution.groupby(['time']).count(),color='red')
plt.hist(substitution.time,color='green',bins=100)
plt.xlabel("Time",fontsize=15)
plt.ylabel("substiution info",fontsize=15)
plt.title("substitution vs time",fontsize=20)
plt.grid()
plt.show()
substitution.groupby(by='time')['time'].count().sort_values(ascending=False).head()
可以看出,比赛中最常换人的是在45min左右,也就是下半场开场的时候。整体趋势来看,下半场是换人最多的时间段。
那么主客队的换人情况又是如何呢?
data=substitution.groupby(['side'])['side'].count() #按照主客队进行分组汇总
plt.pie(data,labels=['home side','away side'],autopct='%.3f%%',startangle=90)
plt.axis('equal')
plt.title("home side VS away side by substitution",fontsize=15)
plt.show()
主客队换人整体占比主客队换人随时间变化趋势
红黄牌趋势分析
很多人会说比赛过程中存在“主场哨”,事实是否如此呢?黄牌趋势
yellowcard=events[events.event_type==4] #黄牌情况信息
plt.figure(figsize=(10,8))
plt.hist(yellowcard.time,bins=10,color='yellow',width=5)
plt.title("yellow card distribution",fontsize=15)
plt.show()