当前位置: 代码迷 >> 综合 >> day8 足球运动员分析
  详细解决方案

day8 足球运动员分析

热度:40   发布时间:2024-02-08 21:58:04.0

足球运动员分析

背景信息

当前,足球运动是最受欢迎的运动之一(也可以说没有之一)。

任务说明

我们的任务,就是在众多的足球运动员中,发现统计一些关于足球运动员的共性,或某些潜在的规律。

数据集描述

数据集包含的是2017年所有活跃的足球运动员。

  • Name 姓名
  • Nationality 国籍
  • National_Position 国家队位置
  • National_Kit 国家队号码
  • Club 所在俱乐部
  • Club_Position 所在俱乐部位置
  • Club_Kit 俱乐部号码
  • Club_Joining 加入俱乐部时间
  • Contract_Expiry 合同到期时间
  • Rating 评分
  • Height 身高
  • Weight 体重
  • Preffered_Foot 擅长左(右)脚
  • Birth_Date 出生日期
  • Age 年龄
  • Preffered_Position 擅长位置
  • Work_Rate 工作效率
  • Weak_foot 非惯用脚使用频率
  • Skill_Moves 技术等级
  • Ball_Control 控球技术
  • Dribbling 盘球(带球)能力
  • Marking 盯人能力
  • Sliding_Tackle 铲球
  • Standing_Tackle 逼抢能力
  • Aggression 攻击能力
  • Reactions 反击
  • Attacking_Position 攻击性跑位
  • Interceptions 抢断
  • Vision 视野
  • Composure 镇静
  • Crossing 下底传中
  • Short_Pass 短传
  • Long_Pass 长传
  • Acceleration 加速度
  • Speed 速度
  • Stamina 体力
  • Strength 强壮
  • Balance 平衡
  • Agility 敏捷度
  • Jumping 跳跃
  • Heading 投球
  • Shot_Power 射门力量
  • Finishing 射门
  • Long_Shots 远射
  • Curve 弧线
  • Freekick_Accuracy 任意球精准度
  • Penalties 点球
  • Volleys 凌空能力
  • GK_Positioning 门将位置感
  • GK_Diving 扑救能力
  • GK_Kicking 门将踢球能力
  • GK_Handling 扑球脱手几率
  • GK_Reflexes 门将反应度
    在这里插入图片描述

导入相关的库

import numpy as np
import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt
mpl.rcParams["font.family"] = "SimHei"
mpl.rcParams["axes.unicode_minus"] = False

加载相关的数据集

  • 加载相关的数据集(注意原数据集中是否存在标题),并查看数据的大致情况。
  • 可以使用head / tail,也可以使用sample。
  • 列没有显式完整,我们需要进行设置。(pd.set_option)
data = pd.read_csv("FullData.csv")
display(data.head(5))
# display(data.sample())
# 当列数较多时,默认情况下列不会显示完整。我们可以通过set_option方法来进行设置。
pd.set_option("display.max_columns", 100)  # 100>53,所以全部显示
display(data.head(5))

在这里插入图片描述

数据探索与清洗

缺失值处理

  • 通过inof查看缺失值信息(以及每列的类型信息)。
  • 可以通过isnull, any, dropna,fillna等方法结合使用,对缺失值进行处理。
# 查看缺失值信息,发现国家队的位置和国家队的号码缺失比较多
# 究其原因:运动员很多,但是能进国家队的就比较少了
display(data.info())

在这里插入图片描述

# 俱乐部不缺失,但是俱乐部中的位置和编号缺失,就不正常了
display(data[data["Club_Position"].isnull()])
# 发现俱乐部位置和编号的缺失都在这里,所以直接将这一条记录过滤掉
data=data[data["Club_Position"].notnull()] # 过滤掉后的数据
# 查看俱乐部位置是否还有缺失值
print(data["Club_Position"].isnull().any()) 

在这里插入图片描述

异常值处理

  • 通过describe查看数值信息。
  • 可配合箱线图辅助。
display(data.describe())

在这里插入图片描述

data[["Age", "Rating"]].plot(kind="box")

在这里插入图片描述

重复值处理

  • 使用duplicate检查重复值。可配合keep参数进行调整。
  • 使用drop_duplicate删除重复值。
# 没有重复值。
display(data.duplicated().any())   # False没有重复值
# 如果存在重复值,则删除重复值。
data.drop_duplicates(inplace=True)

在这里插入图片描述

将身高与体重处理成数值类型,便于分析。

方法1:

# 观察一下身高和体重的信息
display(data.sample())
display(data.info())
# 注意:身高与体重是字符串类型,替换掉cm或kg之后,依然还是字符串类型,不会自动变成数值类型。
# 将cm和kg去掉,并转换成int型
t = data.copy()
t["Height"] = t["Height"].apply(lambda x: x.replace("cm", "")).astype(np.int32)
t["Weight"] = t["Weight"].apply(lambda x: x.replace("kg", "")).astype(np.int32)
display(t.head())
display(t.info())

在这里插入图片描述
在这里插入图片描述
方法2:

# 也可以使用字符串矢量化运算来解决。
data["Height"] = data["Height"].str.replace("cm", "").astype(np.int32)
data["Weight"] = data["Weight"].str.replace("kg", "").astype(np.int32)
data.info()

在这里插入图片描述

运动员的身高,体重,评分信息分布。

# 直方图是离散的统计,核密度图是连续的统计。身高,体重,与评分服从正态分布。
display(data[["Height", "Weight", "Rating"]].plot(kind="hist"))
display(data[["Height", "Weight", "Rating"]].plot(kind="kde"))

在这里插入图片描述

左脚与右脚选手在数量上是否存在偏差?

# 解决方法不止一种。
# 1 通过分组,然后聚合统计。
g = data.groupby("Preffered_Foot")
display(g["Preffered_Foot"].count())
display(g["Preffered_Foot"].count().plot(kind='bar'))

在这里插入图片描述

# 2 通过分组对象的size方法。
display(g["Preffered_Foot"].size())
display(g.size().plot(kind="bar"))

在这里插入图片描述

# 3 使用value_counts
# value_counts 默认根据值数量,按降序来进行排列。
# 我们可以通过ascending参数来控制升序还是降序。
data["Preffered_Foot"].value_counts(ascending=True).plot(kind="bar")

在这里插入图片描述

从球员平均评分上考虑,拥有top10评分能力的俱乐部 / 国家。【超过20人】

# 对俱乐部的分数的平均分统计
g = data.groupby("Club")
display(g["Rating"].mean().sort_values(ascending=False))
v = g["Rating"].agg(["mean", "count"])
v = v[v["count"] > 20]
display(v)
v.sort_values("mean", ascending=False).head(10).plot(kind="bar")

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

# 对国家队统计
g = data.groupby("Nationality")
display(g["Rating"].mean().sort_values(ascending=False))
v = g["Rating"].agg(["mean", "count"])
v = v[v["count"] > 20]
display(v.head(10))
v.sort_values("mean", ascending=False).head(10).plot(kind="bar")

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

哪个俱乐部拥有更多忠心的球员(5年及以上)?

x='07/01/2009'
a=x.split("/")
print(a)
print(a[-1])

在这里插入图片描述

# 获取球员加入俱乐部的年份。
display(data["Club_Joining"].head(2))
year = data["Club_Joining"].map(lambda x: x.split("/")[-1]).astype(np.int)
display(year.head(2))
# 用2017(获取数据的时间)-加入的时间>=5(同时,去掉自由身的球员)
t = data[(2017 - year >= 5) & (data["Club"] != "Free Agents")]
display(t.head(2))
# t.groupby("Club").size()
display(t["Club"].value_counts().head(5))  # 俱乐部超过5年球员的数量
t["Club"].value_counts().head(10).plot(kind="bar")

在这里插入图片描述
在这里插入图片描述

足球运动员是否是出生年月相关?

  1. 全体运动员
  2. 知名运动员(80分及以上)
display(data["Birth_Date"].head(2))
t = data["Birth_Date"].str.split("/", expand=True)  # 矢量化张开成dateframe格式
display(t.head(2))
# display(t[2].value_counts().plot(kind="bar"))  #年
display(t[0].value_counts().plot(kind="bar"))
# display(t[1].value_counts().plot(kind="bar"))

在这里插入图片描述

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

# 去掉替补球员与预备队球员。
display(data["Club_Position"].head(2))
display(data["Club_Kit"].head(2))
t = data[(data["Club_Position"] != "Sub") & (data["Club_Position"] != "Res")]
display(t.groupby(["Club_Kit", "Club_Position"]).size())
t.groupby(["Club_Kit", "Club_Position"]).size().sort_values(ascending=False).head(10).plot(kind="bar")

在这里插入图片描述
在这里插入图片描述

身高与体重是否具有相关性?

# 身高与体重息息相关。
display(data.plot(kind="scatter", x="Height", y="Weight"))  # 相关
# 身高与评分关联性不大。
display(data.plot(kind="scatter", x="Height", y="Rating"))  # 不相关

在这里插入图片描述

哪些指标对评分的影响最大?

data.corr()  # 越大越相关

在这里插入图片描述

假设我们不清楚后2列的具体含义是什么,分析该标题可能的含义。

display(data.head(2))
data.groupby("Club_Position")["GK_Handling"].mean().sort_values(ascending=False).plot(kind="bar")

在这里插入图片描述

年龄与评分具有怎样的关系?

display(data.plot(kind="scatter", x="Age", y="Rating"))  # 不明显

在这里插入图片描述

# 将连续的值切割成离散的形式。
# 注意:cut切割的桶,区间范围与直方图有些不同。cut的区间是前开后闭的形式。(]
# cut方法返回的值默认为我们桶的区间范围值,我们也可以通过labels属性来显式指定具体的标签。
display(pd.cut(data["Age"], bins=5))
display(pd.cut(data["Age"], bins=5, labels=["1区间", "2区间", "3区间", "4区间", "5区间"]).head(5))

在这里插入图片描述

t = data.copy()
# cut方法,如果bins是整数类型,则区间(桶)进行等分设置,如果区间不等分,则我们可以显式设置区间的取值范围。
# # 对bins参数传递一个数组,数组来指定区间的具体值。
t["Age2"] = pd.cut(t["Age"], bins=[1, 20, 30, 40, 100], labels=["初出茅庐", "快速成长", "当打之年", "衰老之年"])
display(t.head(5))
t.groupby("Age2")["Rating"].mean().plot(marker="o", xticks=[0, 1, 2, 3])

在这里插入图片描述