足球运动员的数据分析实战(python) | 您所在的位置:网站首页 › 欧洲杯法国队阵容身价排名最新数据分析图 › 足球运动员的数据分析实战(python) |
一、本案例的相关说明
本人把这篇文章拿出来进行写作的主要原因是为了让大家对数据分析有一个较为清楚的认识,其实数据分析并不是那么高深,只是看你怎么从一堆杂乱无章的数据中能够发现一定的有规律性的结论,有时候可能会觉得某些结论有些牵强,但这属于每个人对每个问题而见解不同,因而较强的数据分析能力,需要我们在实际工作中进行慢慢培养出来。同时这篇文章很好的将pandas库运用到其中,这个也可以帮助我们学以致用,用而学,会起到更好的效果。 1、案例背景足球运动是最受欢迎的运动之一。在此万受瞩目的运动下,打算针对足球运动员个人的信息,技能水平等各项指标进行相关的分析与统计。例如,我们可能会关注如下的内容: 足球运动员是否受出生日期的影响?左撇子适合踢足球吗?足球运动员的号码是否与位置相关?足球运动员的年龄与能力具有怎样的关联? 2、任务说明目前,我们收集到了某年现役运动员的数据集data.csv。我们希望通过该数据集,针对众多的足球运动员进行分析与统计,从而能够发现一些关于足球运动员的特征,解开我们上述疑问。 3、数据列名的含义数据分析指的就是利用统计学知识,对一系列杂乱无章的数据进行数据分析前的预处理,同时结合数据的具体应用场景,提炼出数据中的有效信息,帮助我们定位、分析、解决某些问题,高效决策。 6、数据分析的基本流程明确需求 数据收集 内部数据 购买数据 爬取数据 调查问卷 数据预处理 数据清洗 缺失值 异常值 重复值 数据转换 数据分析 数据建模 数据可视化 编写报告 7、理解流程现在网上最常见的一种比喻数据分析流程的方式,就是利用“炒菜”来对比“数据分析的每个流程”。 做菜步骤数据分析步骤确定做菜明确需求与目的买菜数据收集洗菜数据清洗切菜数据转换炒菜数据分析盛菜数据可视化写日记编写报告 1)熟悉数据集熟悉数据集,就是在进行数据处理之前,应该先熟悉数据,只有对数据充分熟悉之后,才能更好的进行分析。 熟悉数据常用的方法和属性有shape、head()、tail()、sample()、info()、describe()。 shape:以元组形式返回数据集的行、列大小。head()或tail():当数据量过大时,我们不可能直接查看所有数据,这样会很消耗电脑内存,因此,使用head()或tail(),可以默认返回数据集的前五行、后五行的数据;当向head()或tail()中传入整数n时,则可以返回任意前n行、后n行的数据。sample():向方法中传入整数n时,则会从当前数据集中随机抽样n条记录显示出来,对于我们了解数据很有帮助。info():可以显示每列的列名、非空值数量、数据类型,内存占用等信息。describe():可以帮助我们掌握数值的分布情况,会返回每个字段的count()、mean()、std()、min()、25%、50%、75%、max()。对于非数值型字段,只会显示count()计数。 2)缺失值处理缺失值就是由于某些原因导致部分数据为空。进行缺失值处理之前,首先应该查看是否有缺失值。 ① 检查缺失值的办法:一般有以下两种处理方式; 1、通过info查看数据信息。2、可以通过isnull与sum结合,查看缺失值情况。 data.info() data.isnull().sum(axis=0)② 缺失值的处理办法:一般也有两种处理方式; 1、直接删除(当某一列或某一行存在大量的缺失值的时候)。2、采用某个值填充。③ 直接删除缺失值 采用dropna()方法,默认删除所有含有缺失行的数据(即:某一行只有要一个字段缺失,就删除)。传入参数how=”all”,只删除那些全为空的行。 # inplace=True表示原地修改数据集 data.dropna(axis=0, inplace=True) # 对删除后缺失值后的数据集,再次进行缺失值统计 data.isnull().sum(axis=1)④ 填充 可以采用均值、中位数、众数、附近值进行填充。 对于缺失值填充,这里做一个简单的说明:1、当数据服从正态分布,这时候可以采用均值填充;2、当数据为偏态分布(不管左偏还是右偏),则采用中位数进行填充;3、若某个字段为离散型数据,则最好采用众数填充;4、若像温度这样的数据,前后时刻之间的温度关联肯定是最大的,这时采用前后时刻温度进行填充更好。 3)异常值处理异常值:就是和正常数据相比,过高或者过低的数据。 异常值检测:对异常值进行检测,主要有以下几种方式:1、根据业务需求和经验对不同指标所划分的范围,超过指定范围的数据叫做异常值;2、绘制箱线图,大于上边缘和小于下边缘的数据叫做异常值;3、通过descride()函数,可以找出数据的25%和75%分位数,然后把“小于q1+1.5IQR,大于q3+1.5IQR”的数据叫做异常值,q1为25%分位数,q3为75%分位数,IQR= q3- q1的差值。 异常值处理:主要有三种处理办法。1、直接删除;2、把异常值当做缺失值填充;3、把异常值当做特殊情况,研究异常值出现的原因。 4)重复值处理重复数据,指的是数据集中同样的记录有多条。对于这样的数据一般就是直接删除。 重复值的检测:data.duplicated().sum()可以查看,重复数据有多少行。 重复值的删除:data.drop_duplicates(inplace=True)。 上述函数可以配合使用参数subset=[]和keep进行调整,具体需要的时候,再百度自学。 二、数据分析代码 1、导入相关的库 import numpy as np import pandas as pd import matplotlib as mpl import matplotlib.pyplot as plt import seaborn as sns import warnings # 用来显示中文标签 mpl.rcParams["font.family"] = "SimHei" # 用来显示负号 mpl.rcParams["axes.unicode_minus"] = False # 有时候运行代码时会有很多warning输出,像提醒新版本之类的,如果不想这些乱糟糟的输出,可以使用如下代码 warnings.filterwarnings('ignore')结果如下: ① 读取数据集 data = pd.read_csv("G:\\2大数据学习\\data.csv",engine="python",encoding="utf-8-sig") 当文件路径中存在中文时,需要设置engine参数来指定默认引擎为python,否则会报错。utf-8-sig这个编码在windows系统中是常见的。不带有BOM格式的数据才是标准的utf8,但是在windows下,用记事本打开一个文本文件,另存为utf-8格式后,该文件开头就会被带上BOM头信息。这个时候当我们指定编码为utf8,会报错,因此我们就需要指定编码为utf-8-sig,告诉系统该文件的编码是带有BOM格式的utf8编码文件。② 熟悉数据集的几种方式 # 查看数据集共有多少行、多少列 data.shape # 查看数据集的前5行 data.head() # 查看数据集的后5行 data.tail() # 随机从数据集中抽取5行,显示 data.sample(5) # 显示每列的列名、非空值数量、数据类型,内存占用等信息。 data.info() # 此函数可以帮助我们掌握数据的分布情况 data.describe()注意:head()、tail()和sample()方法中都可以传入一个整数值,head(10)表示显示前10行,tail(10)表示显示后10行,sample(10)表示任意抽取10行显示。 ③ 设置DataFrame最大显示列数 DataFrame在显示数据时,若列数较多,中间会将一些列省略掉,变为省略号,而我们往往又需要查看全部列的情况,这个时候就需要设置DataFrame最大显示列数。 pd.set_option("display.max_columns",500)④ 选取指定列,进行相关的数据分析 有时候,数据集中的列,并非都是我们分析所需要的,我们可以有选择性的进行加载,只加载我们需要的信息列(特征列)。 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", "Jumping","Stamina","Strength","Aggression","Interceptions","Positioning", "Vision","Penalties","Marking","StandingTackle", "SlidingTackle","GKDiving", "GKHandling","GKKicking","GKPositioning", "GKReflexes", "Release Clause"] pd.read_csv("G:\\2大数据学习\\data.csv",engine="python",encoding="utf-8-sig",usecols=columns) # 查看数据集共有多少行、多少列 data.shape # 查看数据集的前5行 data.head() # 查看数据集的后5行 data.tail() # 随机从数据集中抽取5行,显示 data.sample(5) # 显示每列的列名、非空值数量、数据类型,内存占用等信息。 data.info() # 此函数可以帮助我们掌握数据的分布情况 data.describe()info()方法的结果显示如下: 结果如下: 结果如下: ① info()方法展示出的信息 ② 利用箱线图,查看异常值 由于数据集列数太多,因此我随意选取两列画出其箱线图进行展示。 sns.boxplot(data=data[["Age", "Overall"]])结果如下: 结果如下: 想要统计身高与体重的分布情况,由于数据集中的身高与体重数据并不是我们熟悉的身高与体重的单位,同时也并不是数值类型的数据,因此处理之前需要我们先做数据转换。 1英尺 = 30.48厘米1英寸 = 2.54厘米1磅 = 0.45千克原始数据展示如下: 处理后的结果展示如下: 结果如下: 结果如下: 结果如下: 由于在综合能力上体现不明显,我们现在通过每个位置,进行更细致的分析。为了分析的客观性,我们只统计左脚与右脚都超过50人(含50人)的位置。 ① 首先,计算哪些位置左右脚球员都达到了50人。 t = data.groupby(["Preferred Foot", "Position"]).size() t = t.unstack() t[t = 20] r = r.sort_values("mean", ascending=False).head(10) display(r) r.plot(kind="bar")结果如下: 结果如下: 结果如下: 我们现有的数据集中,不含有具体的出生日期,因此,我们使用另外一个数据集,该数据集包含2018年世界杯所有球员。 代码如下: data2 = pd.read_csv("G:\\2大数据学习\\wc2018-players.csv",engine="python",encoding="utf-8-sig") 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")结果如下: 足球运动员与出生日期是有关的,在年初出生的运动员要明显多于在年末出生的运动员。 11、足球运动员号码是否与位置相关? 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)结果如下: 这张图就不展示结果了,由于图太大。 14、年龄与评分具有怎样的关系? 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)结果如下: |
CopyRight 2018-2019 实验室设备网 版权所有 |