一、示例分析
目的: 练习pandas模块的使用,数据清洗和数据分析
需求:
运动员的体重分布情况
足球使用左右脚的分析
俱乐部球员分析
运动员与出生日期是否相关
身高与体重相关性
年龄与评分相关性
环境: numpy,pandas,python
二、处理流程介绍
2.1、查看数据的基本情况
import pandas as pd
df = pd.read_csv('FullData.csv')
df.head()
# 设置默认显示的行数
pd.set_option('display.max_rows', 5)
# 设置默认显示的列数
pd.set_option('display.max_columns', 8)
# 查看数据
# 查看数据的形状
# df.shape
# 查看数据的前5行
# df.head()
# 查看数据的后5行
# df.tail()
# 随机查看数据的5行
df.sample(5)
数据详细
字段名 | 备注 |
---|---|
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 | 门将反应度 |
# df.columns
df.columns = ["姓名","国籍","国家队位置","国家队号码","所在俱乐部","所在俱乐部位置","俱乐部号码","加入俱乐部时间","合同到期时间","评分","身高","体重","擅长左(右)脚","出生日期","年龄","擅长位置","工作效率","非惯用脚使用频率","技术等级","控球技术","盘球(带球)能力","盯人能力","铲球","逼抢能力","攻击能力","反映","攻击性跑位","抢断","视野","镇静","下底传中","短传","长传","加速度","速度","体力","强壮","平衡","敏捷度","跳跃","投球","射门力量","射门","远射","弧线","任意球精准度","点球","凌空能力","门将位置感","扑救能力","门将踢球能力","扑球脱手几率","门将反应度"]
2.2、缺值处理
查看数据的数据类型
df.info()
从上述示例可以看到总共17588行,但National_Position(国家队位置) 是1075行,Club_Position (俱乐部位置)17587行。我们知道有的足球运动员是没有进入国家队的,所以National_Position缺值是正常情况。但Club_Position缺值需要处理。
# 查看是否有缺失值
# df['所在俱乐部位置'].isnull().any()
# df['所在俱乐部位置'].isna().any()
# 显示缺失值的数据
# df[df['所在俱乐部位置'].isnull()]
# df[df['所在俱乐部位置'].isna()]
# 没有缺失值的数据
# df2 = df[~df['所在俱乐部位置'].isna()]
# df2 = df[df['所在俱乐部位置'].notna()]
df2 = df[df['所在俱乐部位置'].notnull()]
df2
2.3、异常值处理
describe方法得到数据的描述性统计信息,比如max min,mean,std进行异常值分析。
# 数据的描述性统计信息
# 模拟创造一个异常值
df2.loc[0,'评分'] = 888
df2['评分']
# 发现异常值
# 通过数据的描述性统计信息,查看最小值、最大值
df2.describe()
# 通过条件判断筛选
df2[df2['评分'] < 0]
df2[df2['评分'] > 100]
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif']=['SimHei'] #指定默认字体 SimHei为黑体
# 通过图形化的方式查看异常值 -- 使用箱线图辅助查看异常值
# df2.plot(kind='box')
# df2.boxplot(column='评分')
# 然后确认异常值的原因
# 获取评分 和盯人能力
df2[['盯人能力','评分']].plot(kind='box')
df2['盯人能力'].describe()
# 对数据进行修改
df2.loc()[0,'评分'] = 94
df2['评分']
2.4 、重复值处理
# 查看是否有重复数据
# df2.duplicated().any()
# 查看没有重复的数据
# df2[~df2.duplicated()]
# 删除重复的数据 默认所有列都重复才删除
# df2.drop_duplicates()
# 指定列重复才删除
# 查看是否有重复值,指定某列重复才算重复,使用subset参数
# df2.duplicated(subset=['姓名']).any()
# 获取重复值数据
# df2[df2.duplicated(subset=['姓名'])]
# 获取没有重复值的数据,通过数据筛选
# df2[~df2.duplicated(subset=['姓名'])]
# 删除重复值
df3 = df2.drop_duplicates(subset=['姓名'], inplace=True)
df3
# 原有的df2是替换数据
# df2.drop_duplicates(inplace=True)
2.5 、数据预处理 身高/体重
运动员身高和体重分布
从查看数据结果可以看到运动员身高Height、体重Weight的数据后都添加了相应的单位。要分析运动员身高和体重的分布,首先需要将身高Height和Weight数据的单位去掉。
# 去掉身高和体重的单位,通过字符串的替换
# df3['身高'] = df3['身高'].str.replace('cm','').astype('int')
# df3['体重'] = df3['体重'].str.replace('kg','').astype('int')
df3[['身高','体重']]
df3[['身高','体重']].info()
# # 通过apply方式
# def handle_cm(v:str) -> int:
# return int(v.replace('cm',''))
# df3['身高'] = df3['身高'].apply(handle_cm)
# # 使用匿名函数的方式 lambda
# df3['体重'] = df3['体重'].apply(lambda v:int(v.replace('kg','')))
2.6 、数据预处理 身高/体重/ 评分分布
# 1. 通过命令的方式 describe
# 查看数据的分布情况
# df3[['身高','体重']].describe()
# 2. 通过图形化的方式 直方图、密度图
# 画图的方式 matplotlib\ pandas
# 导入模块
import matplotlib.pyplot as plt
# 通过matplotlib画直方图
# plt.hist(df3['身高'],bins=15)
# # 通过pandas画直方图
# df3['身高'].hist(bins=15)
# df3['体重'].hist(bins=15)
# # pip install scipy==1.11.2
# # 通过pandas画密度图
df3['身高'].plot(kind='kde')
df3['体重'].plot(kind='kde')
2.7 、数据分析 分析左右脚使用习惯
#【示例】查看足球运动员左脚右脚使用情况
df['擅长左(右)脚'].head(10)
可以看到,足球运动员踢球有使用左脚也有使用右脚。要统计使用左脚和右脚的数量,需要按Preffered_Foot进行分组,计算其count()值。我们可以使用饼状图来显示左脚右脚选手数量的差别。
# 使用饼状图来显示左脚右脚选手数量的差别
# df3['擅长左(右)脚'].head(10)
g = df3.groupby('擅长左(右)脚')
s = g['擅长左(右)脚'].count()
s.plot(kind='pie',autopct='%.2f')
# value_counts()方法的使用
foot_counts = df3['擅长左(右)脚'].value_counts()
foot_counts.plot(kind='pie',autopct='%.2f')
# 使用条形图来显示左脚右脚选手数量的差别
# 上面的操作,其实就是针对擅长左(右)脚分组,再统计每组的数量
df3['擅长左(右)脚'].value_counts().plot(kind='barh', fontsize=15)
2.8、数据分析 俱乐部球员评分分析
从球员评分角度分析,拥有top10评分能力俱乐部。
# 获取评分前10的运动员
# df3[['姓名','评分']].sort_values(by='评分', ascending=False).head(10)
df3[['姓名','评分','所在俱乐部']].sort_values(by='评分',ascending=False).head(10)
# 获取前10的俱乐部,根据球员的评分
dfg1 = df3.groupby('所在俱乐部')
dfg1['评分'].mean().sort_values(ascending=False).head(10)
# 对俱乐部人数大于25人的俱乐部,平均评分进行排序取前10
# 查看俱乐部的球员的人数和球员的评分
rs1 = dfg1['评分'].agg(['mean','count'])
# 查看俱乐部的球员人数,球员的平均分,过滤掉人数小于25
# rs1['count'] >= 25
# 查看俱乐部的球员人数,球员的平均分,过滤掉人数小于25,排名前10的俱乐部
# rs1[rs1['count'] >= 25].sort_values(by='mean',ascending=False).head(10)
# 根据排名进行绘制图表
rs1[rs1['count'] >= 25].sort_values(by='mean',ascending=False).head(10).plot(kind='bar')
2.9、数据分析 足球运动员与出生日期的关系
# 获取足球运动员日期
# 获取出生日期
# df['出生日期']
# 切分
t = df['出生日期'].str.split('/',expand=True)
# t
# 对月份进行分析:根据月份来分组,统计每一个月对应的球员数量,最后柱状图表示
# t[0].value_counts(ascending=False).plot(kind='bar') # 月
# t[1].value_counts(ascending=False).plot(kind='bar') # 日
t[2].value_counts(ascending=False).plot(kind='bar') # 年
# 评分大于等于80的球员数据
result = df[df['评分'] > 80]
# result
t = result['出生日期'].str.split('/',expand=True)
# t
# 通过图表分析和月是否有关
# t[0].value_counts(ascending=False).plot(kind='bar')
# 通过图表分析和日是否有关
# t[1].value_counts(ascending=False).plot(kind='bar')
# 通过图表分析和年是否有关
t[2].value_counts(ascending=False).plot(kind='bar')
2.10、数据分析 身高与体重是否具有相关性
# 通过散点图查看变量之间的关系 身高和体重
# df3.plot(kind='scatter',x='身高',y='体重')
# 身高和评分之间的关系
# df3.plot(kind='scatter',x='身高',y='评分')
# 使用相关系数描述身高和体重之间的关系
# df3['身高'].corr(df3['体重'])
# df3['身高'].corr(df3['评分'])
df3[['身高','体重','评分']].corr()
# 与评分相关性强的指标有哪些
# 筛选和评分相关性的数据
# df3.select_dtypes(include=['number']).corr()
# df3.select_dtypes(include=['number']).corr()['评分']
# 筛选和评分相关性的数据,比较强的前10个指标
# select_dtypes(include=['number'])指定选择的数据类型为整型的才进行整理和处理
df3.select_dtypes(include=['number']).corr()['评分'].sort_values(ascending=False).head(10)
2.11、数据分析 探索分析数据之间的相关性
# 年龄与评分是否相关
# 查看评分和年龄的相关性
# df3.plot.scatter(x='年龄',y='评分')
# 对年龄进行分组
# pd.cut(df3['年龄'],bins=4,labels=['青年','中年','壮年','老年'])
# 将切分好的数据,添加到原来的数据中
df3['age'] = pd.cut(df3['年龄'],bins=4,labels=['青年','中年','壮年','老年'])
# # 按照年龄分组,查看评分的情况
# df3.groupby('age')['评分'].mean()
# # 通过图表,按照年龄分组,查看评分的情况
df3.groupby('age')['评分'].mean().plot(kind='line')
# 按照年龄分组,指定分组的边界
pd.cut(df3['年龄'],bins=[10,30,40,50],labels=['青年','中年','壮年'])