数据集
数据集
背景:
我们关注足球运动员的如下内容:
- 足球运动员是否受出生日期的影响?
- 左撇子适合踢足球吗?
- 足球运动员的号码是否与位置有关?
- 足球运动员的年龄与能力具有怎样的关联?
-
哪些技能会对足球运动员的综合能力造成较大的影响?
任务说明:
这是2019年现役运动员的数据集,我们希望通过该数据集,针对众多的足球运动员进行分析与统计,从而能够发现一些关于足球运动员的特征
数据集描述
数据集包含的是2019年现役的足球运动员
列名 含义
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.编写报告
下面代码和模块的实现都是基于上面的步骤去做的,里面使用的数学公式和数学公式都可以百度处理!数据分析的大体步骤就是上面的几步,其中比较重要的就是数据的预处理和数据的分析(也就是数据建模)
导入相关的库
//导入需要的库,同时进行一些初始化的设置
import numpy as np
import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt
import warnings//忽略告警,没有多大意义
这里数据的可视化两个混合使用:matplotlib和seaborn
import seaborn as sns
sns.set(style="darkgrid",font="SimHei",font_scale=1.5,rc={"axes.unicode_minus":False})
warnings.filterwarnings("ignore")
1.加载数据,使用pandas库
- https://blog.csdn.net/qq_27171347/article/details/81509936(加载数据函数的说明,不再赘述)
//读取参数指定的文件,返回一个DataFrame类型的对象,pandas一共返回两种数据类型,百度就知
data=pd.read_csv("data.csv")
数据加载进来就需要看看数据一共多少行一共多少列等一些问题,这个时候可以使用
- data.shape()--shape函数是numpy.core.fromnumeric中的函数,它的功能是读取矩阵的长度
print(data.shape)
下面的自行检验,不再截图,使用哪个函数全看自己的爱好,就是看一下数据加载的对不对和原始数据对照一下,仅此而已!!!!!
- data.head()--它是pandas中的,回车返回的是前五行的数据
- data.tail()
- data.sample(),随机显示出来一行(个人感觉)
数据加载进来了,看看叶都是正确的,可是一看数据好多列,我们需要的也就是那几列,我们只要加载需要的那几列就行啦!!!!!下面将依照这个思路把数据重新加载一遍
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()
//设置显示的最大列数
pd.set_option("max_columns",100)
data.head()
2.数据预处理
数据清洗
缺失值处理,异常值处理,重复值处理(好像就是这几种数据需要处理)
通过info查看数据信息。
//info方法可以显示每列名称,非空值数量,每列的数据类型,内存占用等信息
data.info()
//显示
data.isnull().sum(axis=0)
//删除所有含有空值的行,就地修改
data.dropna(axis=0,inplace=True)
data.isnull().sum()
- 异常值处理--通过describe查看数值信息。可配合箱线图辅助
- 重复值处理--使用duplicate检查重复值。可配合keep参数进行调整,使用drop_duplicate删除重复值
到这里,数据的预处理就结束了,在进行数据预处理的时候基本都是这三个方面(可能以偏概全了),下面要就是根据公司老总的需要慢慢的写代码实现了----就是以目的为驱使的数据分析
足球运动员的身高体重分布
观看数据发现身高与体重的记录目前并不是数值类型,我们需要进行转换
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", ""))return v * 0.45data["Height"] = data["Height"].apply(tran_height)
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])
左撇子适合踢足球吗?
我们首先从球员数量上进行一下统计
number = data["Preferred Foot"].value_counts()
print(number)
sns.countplot(x="Preferred Foot", data=data)
然后,我们再从球员综合能力上进行衡量
print(data.groupby("Preferred Foot")["Overall"].mean())
sns.barplot(x="Preferred Foot", y="Overall", data=data)
由于综合能力上体现不明显,我们现在通过每个位置,进行更细致的分析,为了分析的客观性,我们只统计左脚与右脚都超过50人的位置。
//首先我们计算哪些位置左右脚球员都达到50人
t = data.groupby(["Preferred Foot", "Position"]).size()
t = t.unstack()
t[t < 50] = np.NaN
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)
从结果可以清晰得知,左脚选手更适合RW(右边锋)的位置
写到这里吧!!!后面复制一下手头资料中的代码!!!!代码亲测真是可靠,可运行,下周更新一下其他的吧!!!!
哪个的俱乐部 / 国家拥有综合能力更好的球员(top10)。
由于每个俱乐部/国家队人数不一,为了统计的客观性,只考虑人数达到一定规模的俱乐部/国家。
//俱乐部
g = data.groupby("Club")
r = g["Overall"].agg(["mean", "count"])
r = r[r["count"] >= 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]
r = r.sort_values("mean", ascending=False).head(10)
display(r)
r.plot(kind="bar")
哪个俱乐部拥有效力更久的球员(5年及以上)
t = pd.to_datetime(data["Joined"])
t = t.astype(np.str)
join_year = t.apply(lambda item: int(item.split("-")[0]))
over_five_year = (2018 - join_year) >= 5
t2 = data[over_five_year]
t2 = t2["Club"].value_counts()
# display(t2)
t2.iloc[:15].plot(kind="bar")
足球运动员是否是出生日期相关?
我们现有的数据集中,不含有具体的出生日期,因此,我们使用另外一个数据集,该数据集包含2018年世界杯所有
球员
data2 = pd.read_csv("wc2018-players.csv")
data2.head()
t = data2["Birth Date"].str.split(".", expand=True)
t[0].value_counts().plot(kind="bar")
# t[1].value_counts().plot(kind="bar")
# t[2].value_counts().plot(kind="bar")
# t[2].value_counts().sort_index().plot(kind="bar")
足球运动员号码是否与位置相关?
g = data.groupby(["Jersey Number", "Position"])
t = g.size()
display(t)
t = t[t >= 100]
t.plot(kind="bar")
身价与薪水,违约金是否相关?
因为身价与违约金的单位既有M,也有K,我们统一K单位,同时,将类型转换为数值类型,便于统计。
def to_numeric(item):
item = item.replace("€", "")
value = float(item[:-1])
if item[-1] == "M":
value *= 1000
return value
data["Value"] = data["Value"].apply(to_numeric)
data["Wage"] = data["Wage"].apply(to_numeric)
data["Release Clause"] = data["Release Clause"].apply(to_numeric)
data.head()
# sns.scatterplot(x="Value", y="Wage", data=data)
# sns.scatterplot(x="Value", y="Release Clause", data=data)
# sns.scatterplot(x="Value", y="Height", data=data)
哪些指标对综合评分的影响较大?
# data.corr()
plt.figure(figsize=(25, 25))
sns.heatmap(data.corr(), annot=True, fmt=".2f", cmap=plt.cm.Greens)
plt.savefig("corr.png", dpi=100, bbox_inches="tight")
分析某项未标记的技能
假设因为某种原因,GKDiving列的标题没有成功获取,现在分析该技能可能表示的含义。
g = data.groupby("Position")
g["GKDiving"].mean().sort_values(ascending=False)
plt.figure(figsize=(15, 5))
sns.barplot(x="Position", y="GKDiving", data=data)
年龄与评分具有怎样的关系
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)
好了,下面就可以做总结了
1.左撇子相对于右撇子来说,并无明显劣势,其更适合右边锋的位置。
2. 知名俱乐部平均能力更好的球员,但并非球员平均能力越好,球队的成绩就越好。
3. 一些知名足球国家,在球员的平均能力上可能并没有非常靠前,只是因为足球运动员较多,进而个别球员较知
名而已。
4. 足球运动员与出生日期是有关的,在年初出生的运动员要明显多于在年末出生的运动员。
5. 足球运动员的号码与位置是相关的,例如,1号通常都是守门员,9号通常是中锋等。
6. 足球运动员的身价与其薪水是紧密关联的,尤其是违约金,与身价的关联更大。
7. Reactions(反应)与Composure(沉着)两项技能对总分的影响最大。
8. 随着年龄的增长,球员得到更多的锻炼与经验,总体能力提升,但三十几岁之后,由于体力限制,总体能力下
降。