小乐数据

python预测足球比赛胜率 python足球分析

原创  数据分析 2024年11月05日 14:42:11 ly 1评论 65

利用Python进行足球远动员分析

分析步骤

1、明确需求与目的

数据预览

提出问题

2、数据预处理

数据清洗

缺失值

异常值

重复值

数据转换

3、数据分析

问题1左撇子适合踢足球吗?

问题2 哪个俱乐部或国家队的球员整体实力比较强

问题3 足球运动员是否受出生日期的影响

问题4 足球运动员的号码是否与位置相关

问题5 足球运动员的年龄与能力具有怎样的关联

问题6 哪些因素会对足球运动员的综合能力造成较大的影响

4、总结


分析步骤

1、明确需求与目的

身为一个足球资深球迷,本人对足球远动员的一些比赛数据非常感兴趣。足球运动员孰强孰弱的争论喋喋不休,不妨让数据来说话,让数据来体现?


数据预览





拿到数据,首先要明确各个列标签的含义


Name | 球员姓名

Age | 年龄

Nationality | 国籍

Overall | 综合能力评分

Potential | 潜能评分

Club | 所属俱乐部

Value | 球员身价

Wage | 周薪

Preferred Foot | 惯用脚

Position | 最佳位置

Jersey Number | 运动衫号码

Joined | 加入俱乐部时间

Height | 身高

Weight | 体重

Crossing | 传中

Finishing | 射术

HeadingAccuracy | 头球精度

ShortPassing | 短传

Volleys | 凌空

Dribbling | 盘带

Curve | 弧线

FKAccuracy | 任意球精度

LongPassing | 长传

BallControl | 控球

Acceleration | 加速

SprintSpeed | 速度

Agility | 敏捷

Reactions | 反应

Balance | 平衡

ShotPower | 射门力量

Jumping | 弹跳

Stamina | 体能

Strength | 强壮

LongShots | 远射

Aggression | 侵略性

Interceptions | 拦截意识

Positioning | 跑位

Vision | 视野

Penalties | 点球

Composure | 沉着

Marking | 盯人

StandingTackle | 抢断

SlidingTackle | 铲球

GKDiving | 鱼跃

GKHandling | 手形

GKKicking | 开球

GKPositioning | 站位

GKReflexes | 反应

Release Clause | 违约金


提出问题

1、左撇子适合踢足球吗?

2、哪个俱乐部或国家队的球员整体实力比较强?

3、足球运动员是否受出生日期的影响?

4、足球运动员的号码是否与位置相关?

5、足球运动员的年龄与能力具有怎样的关联?

6、哪些因素会对足球运动员的综合能力造成较大的影响?


2、数据预处理

第一步导入相关的库


import numpy as np

import pandas as pd

import matplotlib as mpl

import matplotlib.pyplot as plt

import warnings

# mpl.rcParams["font.family"] = "SimHei"

# mpl.rcParams["axes.unicode_minus"] = False

import seaborn as sns

sns.set(style="darkgrid", font="SimHei", font_scale=1.5, rc={"axes.unicode_minus": False})

warnings.filterwarnings("ignore")


第二步加载相关数据集


# 读取参数指定的文件,返回一个DataFrame类型的对象。

data = pd.read_csv("data.csv")

print(data.shape)#返回数据行列数

# data.head(3)#查看开头指定列数

# data.tail()#查看末尾指定列数

data.sample(10)#随机取指定列数





但并非所有的数据都对分析是有用的,应有选择性地取舍


columns = ["Name", "Age", "Nationality", "Overall", "Potential", "Club", "Value", "Wage", "Preferred Foot",

          "Position", "Jersey Number", "Joined", "Height", "Weight", "Crossing", "Finishing",

          "HeadingAccuracy", "ShortPassing", "Volleys", "Dribbling", "Curve", "FKAccuracy", "LongPassing",

          "BallControl", "Acceleration", "SprintSpeed", "Agility", "Reactions", "Balance", "ShotPower", 

          "Jumping", "Stamina", "Strength", "LongShots", "Aggression", "Interceptions", "Positioning", "Vision",

          "Penalties", "Composure", "Marking", "StandingTackle", "SlidingTackle", "GKDiving", "GKHandling",

          "GKKicking", "GKPositioning", "GKReflexes", "Release Clause"]

# 参数指定所要读取的列。

data = pd.read_csv("data.csv", usecols=columns)

data.head()




数据清洗

缺失值

通过info查看数据信息。

也可以通过isnull与sum结合,查看缺失值情况。


# info方法可以显示每列名称,非空值数量,每列的数据类型,内存占用等信息。

# data.info()

data.isnull().sum(axis=0)#axis=0表示以列为基准

1.

2.

3.





缺失值不足占总数据的%10左右,可以直接删去。但达到%30左右及以上,我们可以采用填充的方法,均值中值或者众数来填充视情况而定。


# 删除所有含有空值的行。就地修改。

data.dropna(axis=0, inplace=True)

data.isnull().sum()

1.

2.

3.

异常值

通过describe查看数值信息。

可配合箱线图辅助。

异常值可以删除,视为缺失值,或者不处理。


data.describe()

1.



sns.boxplot(data=data[["Age", "Overall"]])

1.





箱线图包括最小值,四分之一位点q1,中位点,四分三位点q3,最大值,离群点。


离群点定义为小于q1 - 1.5IQR,大于q3 + 1.5IQR(q3-q1=IQR)。


离群点可能为异常值,但就此看这些离群点都是算在一个合理的范围内的。


重复值

使用duplicate检查重复值。可配合keep参数进行调整。

使用drop_duplicate删除重复值。


data.duplicated().sum()

# data.drop_duplicates(inplace=True)


数据没有重复值,不做处理。若有重复值,可用drop_duplicates方法


数据转换

我们要统计身高与体重的分布情况,不过,身高与体重目前并不是数值类型,我们需要进行转换后,才能进行统计计算。这里,我们将身高与体重转换成熟悉的单位。

1英尺 = 30.48厘米

1英寸 = 2.54厘米

1磅 = 0.45千克


# 定义转换函数

def tran_height(height):

    v = height.split("'")#以指定符号分割形成列表

    return int(v[0]) * 30.48 + int(v[1]) * 2.54


def tran_weight(weight):

    v = int(weight.replace("lbs", ""))#去掉lbs单位,转换为int型计算

    return v * 0.45


data["Height"] = data["Height"].apply(tran_height)#apply对列的每个对象调用函数

data["Weight"] = data["Weight"].apply(tran_weight)


转换后做个密度图观察下分布


fig, ax = plt.subplots(1, 2)#创建对象

fig.set_size_inches((18, 5))#设置大小

sns.distplot(data[["Height"]], bins=50, ax=ax[0], color="g")#第一个对象为身高的密度图

sns.distplot(data["Weight"], bins=50, ax=ax[1])#第二个对象为体重的密度图




3、数据分析

问题1左撇子适合踢足球吗?

左撇子适合踢足球吗?


先在数量上做个对比


number = data["Preferred Foot"].value_counts()#统计不同对象的数量

print(number)

sns.countplot(x="Preferred Foot", data=data)#作柱状图






再进行能力值上的对比


print(data.groupby("Preferred Foot")["Overall"].mean())#groupby对指定列进行分组,对能力值列求平均值

sns.barplot(x="Preferred Foot", y="Overall", data=data)






还可以进行特定位置的对比


t = data.groupby(["Preferred Foot", "Position"]).size()#对惯用足和位置分组,显示数量

t = t.unstack() #以表格展示

t[t < 50] = np.NaN #数量太小的位置比对不具代表性。所以把小于50的列置为空值,后面删除

t.dropna(axis=1, inplace=True)

display(t)




t2 = data[data["Position"].isin(t.columns)] #选取过滤后的列

plt.figure(figsize=(18, 10))

sns.barplot(x="Position", y="Overall", hue="Preferred Foot", hue_order=["Left", "Right"], data=t2)





经过这样的比对后,可以发现右边锋位置,左脚球员评分比右脚球员高很多。


以我的看球经验,应该是右边锋位置,一般内切左脚射门效率高,其中典型的有著名球星罗本。


问题2 哪个俱乐部或国家队的球员整体实力比较强

俱乐部


g = data.groupby("Club") #以俱乐部分组

r = g["Overall"].agg(["mean", "count"]) #形成以总评的均值和数量的对象

r = r[r["count"] >= 20] #过滤球员数小于20的俱乐部

r = r.sort_values("mean", ascending=False).head(10) #按均值降序排列,显示前十名

display(r)

r.plot(kind="bar")






前十名中有尤文图斯、巴塞罗那、皇家马德里、罗马、巴黎圣日耳曼在列,结果比较符合认知。


国家队


同样的方法分析国家队


g = data.groupby("Nationality") #按国籍分组

r = g["Overall"].agg(["mean", "count"]) #按评分的均值、数量创建对象

r = r[r["count"] >= 50] #过滤数量不足50人的国家队

r = r.sort_values("mean", ascending=False).head(10) #按均值的降序排列前十名

display(r)

r.plot(kind="bar")




问题3 足球运动员是否受出生日期的影响

t = data2["Birth Date"].str.split(".", expand=True) #将出生日期转换为字符串,以.分割成年月日形成新的DF对象

# t[0].value_counts().plot(kind="bar")

# t[1].value_counts().plot(kind="bar")

t[2].value_counts().sort_index().plot(kind="bar") #按升序排列的各年的数量作图



问题4 足球运动员的号码是否与位置相关

g = data.groupby(["Jersey Number", "Position"])

t = g.size()

# display(t)

t = t[t >= 100]

t.plot(kind="bar")




问题5 足球运动员的年龄与能力具有怎样的关联

可以做散点图比较

也可以看年龄对总评的协方差来看两者的关系


sns.scatterplot(x="Age", y="Overall", data=data)

data["Age"].corr(data["Overall"])




结果太过于分散,可以分区间比较


# 对一个数组进行切分,可以将连续值变成离散值。

# bins 指定区间数量(桶数)。bins如果为int类型,则进行等分。

# 此处的区间边界与为前开后闭。

# pd.cut(t["Age"], bins=4)

# 如果需要进行区间的不等分,则可以将bins参数指定为数组类型。

# 数组来指定区间的边界。

min_, max_ = data["Age"].min() - 0.5, data["Age"].max()

# pd.cut(t["Age"], bins=[min_, 20, 30, 40, max_])

# pd.cut 默认显示的内容为区间的范围,如果我们希望自定义内容(每个区间显示的内容),可以通过labels参数

# 进行指定。

t = pd.cut(data["Age"], bins=[min_, 20, 30, 40, max_], labels=["弱冠之年", "而立之年","不惑之年", "知天命"])

t = pd.concat((t, data["Overall"]), axis=1) #按列方向拼接总评列

g = t.groupby("Age")

display(g["Overall"].mean())

sns.lineplot(y="Overall", marker="*", ms=30, x="Age", data=t)




问题6 哪些因素会对足球运动员的综合能力造成较大的影响

plt.figure(figsize=(25, 25))

sns.heatmap(data.corr(), annot=True, fmt=".2f", cmap=plt.cm.Greens)


观察哪个因素对总评的协方差较大


4、总结

左撇子相对于右撇子来说,并无明显劣势,但更适合右边锋的位置。

知名俱乐部平均能力更好的球员,但并非球员平均能力越好,球队的成绩就越好。

一些知名足球国家,在球员的平均能力上可能并没有非常靠前,只是因为足球运动员较多,进而个别球员较知名而已。

足球运动员的号码与位置是相关的,例如,1号通常都是守门员,9号通常是中锋等。

随着年龄的增长,球员得到更多的锻炼与经验,总体能力提升,但三十几岁之后,可能由于体力限制,总体能力下降。

Reactions(反应)与Composure(沉着)两项技能对总分的影响最大。



足球软件下载:

http://lcsjfx.com/SoccerPredictor/DownLoad


抱歉,评论功能已关闭!

选择主题