探索性数据分析-足球赛事数据集

挑战

在下面查看之前,请尝试回答有关数据集的一些高级问题。

我们如何操作裁判给黑皮球员更多红牌的问题?

  • 反事实:如果球员体重较轻,裁判在同样的条件下可能会给同一个犯规者一张黄牌或无牌。
  • 回归:考虑到混杂因素,深色玩家对比例红牌/总牌的回归系数为正。

潜在问题

  • 如何将Rater1和Rater2结合起来?平均?如果他们不同意怎么办?把它扔掉?
  • 数据是否失衡,即红牌非常罕见?
  • 数据是否有偏差,即玩家有不同的游戏时间?这是他们整个职业生涯的总结吗?
  • 我怎么知道我已经解释了所有形式的混淆?### 首先,是否对所有参考文献都有系统的区分?

探索/假设:

  • 游戏分布
  • 红牌vs游戏
  • 每局游戏的红牌与每局游戏的总牌数(按肤色)
  • 按平均肤色对所有玩家的每场游戏分配红、黄、总牌数和分数红
  • 玩家遇到了多少裁判?
  • 有没有一些俱乐部更具侵略性,得到更多的卡?还是更保守,得到更少?
  • 梳毛会因国家而异吗?
  • 高分者在同一位置得到更多的松弛(更少的牌)吗?
  • 有没有裁判员的红牌/黄牌比其他裁判员多?
  • 评分者的一致性如何?看看科恩的卡帕。
  • 红牌的位置有什么不同?比如防守队员得到更多?
  • 有更多游戏的玩家会得到更多的牌吗?皮肤颜色有区别吗?
  • 是否显示偏差取决于参考国家?

了解数据的组织方式

  • 数据集是一个单独的csv,它将裁判和球员之间的每一个交互聚合成一行。换句话说:裁判员A裁判员A裁判员B裁判员参加了10场比赛,在这10场比赛中给了2张红牌。然后在数据集中会有一个唯一的行,它说:
    裁判A,球员B,2张红牌……
  • 这有几个含义,使得理解和处理这些数据的第一步有点棘手。首先,关于球员B的信息每次都会重复,这意味着如果我们简单地对某个指标进行平均,我们可能会得到误导性的结果。
    例如,问“运动员的平均体重是多少?”

1.数据读取与预处理

1.1 查看数据

#from __future__ import absolute_import, division, print_function
import matplotlib as mpl
from matplotlib import pyplot as plt
from matplotlib.pyplot import GridSpec
import seaborn as sns
import numpy as np
import pandas as pd
import os, sys
from tqdm import tqdm
import warnings
warnings.filterwarnings('ignore')
sns.set_context("poster", font_scale=1.3)

#import missingno as msno
#import pandas_profiling

from sklearn.datasets import make_blobs
import time
df = pd.read_csv("redcard.csv.gz", compression='gzip')
df.shape

在这里插入图片描述

df.head()

在这里插入图片描述

df.describe().T

在这里插入图片描述

1.2 查看数据类型

df.dtypes

在这里插入图片描述

1.3 查看列

all_columns = df.columns.tolist()
all_columns

在这里插入图片描述

2.数据切分模块

2.1 球员的特征信息汇成透视表

player_index = 'playerShort'  #选手
player_cols = [#'player', # drop player name, we have unique identifier
               'birthday',
               'height',
               'weight',
               'position',
               'photoID',
               'rater1',
               'rater2',
              ]
all_cols_unique_players = df.groupby('playerShort').agg({col:'nunique' for col in player_cols})
all_cols_unique_players.head()              

在这里插入图片描述

2.2 查看球员信息有无重复

all_cols_unique_players[all_cols_unique_players > 1].dropna().head()

在这里插入图片描述
没有重复值!

2.3 查看球员重复信息函数

def get_subgroup(dataframe, g_index, g_columns):
    
    """Helper function that creates a sub-table from the columns and runs a quick uniqueness test."""
    g = dataframe.groupby(g_index).agg({col:'nunique' for col in g_columns})
    if g[g > 1].dropna().shape[0] != 0:
        print("Warning: you probably assumed this had all unique values but it doesn't.")
    return dataframe.groupby(g_index).agg({col:'max' for col in g_columns})
  • 调用函数
players = get_subgroup(df, player_index, player_cols)
players.head()

在这里插入图片描述

2.4 保存数据函数

def save_subgroup(dataframe, g_index, subgroup_name, prefix='raw_'):
    save_subgroup_filename = "".join([prefix, subgroup_name, ".csv.gz"])
    dataframe.to_csv(save_subgroup_filename, compression='gzip', encoding='UTF-8')
    test_df = pd.read_csv(save_subgroup_filename, compression='gzip', index_col=g_index, encoding='UTF-8')
    # Test that we recover what we send in
    if dataframe.equals(test_df):
        print("Test-passed: we recover the equivalent subgroup dataframe.")
    else:
        print("Warning -- equivalence test!!! Double-check.")
  • 调用函数
save_subgroup(players, player_index, "players")

在这里插入图片描述

2.5 俱乐部与国家的关系

club_index = 'club'
club_cols = ['leagueCountry']
clubs = get_subgroup(df, club_index, club_cols)
clubs.head()

在这里插入图片描述

  • 查看特征数量
clubs['leagueCountry'].value_counts()

在这里插入图片描述

  • 保存文件
save_subgroup(clubs, club_index, "clubs", )

2.6 裁判和裁判国家的关系

referee_index = 'refNum'
referee_cols = ['refCountry']
referees = get_subgroup(df, referee_index, referee_cols)
referees.head()

在这里插入图片描述

  • 查看裁判的国家数
referees.refCountry.nunique()

在这里插入图片描述
裁判来自161个不同的国家

  • 查看数据形状
referees.shape

在这里插入图片描述
3147名裁判

  • 保存模型
save_subgroup(referees, referee_index, "referees")

2.7 裁判和球员的关系

dyad_index = ['refNum', 'playerShort']
dyad_cols = ['games',
             'victories',
             'ties',
             'defeats',
             'goals',
             'yellowCards',
             'yellowReds',
             'redCards',
            ]
dyads = get_subgroup(df, g_index=dyad_index, g_columns=dyad_cols)
dyads.head()            

在这里插入图片描述

  • 查看形状
dyads.shape

在这里插入图片描述

  • 查看球员红牌超1个的信息
dyads[dyads.redCards > 1].head(10)

在这里插入图片描述

  • 保存模型
save_subgroup(dyads, dyad_index, "dyads")

3. 缺失值可视化分析

3.1 安装missingno缺失值库

在这里插入图片描述

3.2 missingno.matrix缺失值分布图

players = load_subgroup("raw_players.csv.gz")
players.shape
players.head()

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

msno.matrix(players.sample(500),
            figsize=(16, 7),
            width_ratios=(15, 1))

在这里插入图片描述

3.3 missingno.matrix缺失值直方图

msno.bar(players.sample(500))

在这里插入图片描述

3.4 missingno.heatmap查看缺失值之间的相关性

msno.heatmap(players.sample(500),
            figsize=(16, 7),)

在这里插入图片描述
如photoID缺失,rate2 100%缺失

3.5 查看缺失值数量

print("All players:", len(players))
print("rater1 nulls:", len(players[(players.rater1.isnull())]))
print("rater2 nulls:", len(players[players.rater2.isnull()]))
print("Both nulls:", len(players[(players.rater1.isnull()) & (players.rater2.isnull())]))

在这里插入图片描述

  • 去除rate1
    缺失值
players = players[players.rater1.notnull()]
players.shape[0]

在这里插入图片描述

  • 查看缺失值直方图
msno.matrix(players.sample(500),
            figsize=(16, 7),
            width_ratios=(15, 1))

在这里插入图片描述
可以看到,与rater1相关的rater2和photoID都没有缺失值

  • 按类别分组,统计各个分组中值的频数
pd.crosstab(players.rater1, players.rater2)

在这里插入图片描述

  • 画出各个分组中值的频数热力图
fig, ax = plt.subplots(figsize=(12, 8))
sns.heatmap(pd.crosstab(players.rater1, players.rater2), cmap='Blues', annot=True, fmt='d', ax=ax)
ax.set_title("Correlation between Rater 1 and Rater 2\n")
fig.tight_layout()

在这里插入图片描述

3.6 取评分平均值

players['skintone'] = players[['rater1', 'rater2']].mean(axis=1)
players.head()

在这里插入图片描述

  • 画出评分平均值的分布
sns.distplot(players.skintone, kde=False);

在这里插入图片描述

3.7 位置信息的统计与划分

MIDSIZE = (12, 8)
fig, ax = plt.subplots(figsize=MIDSIZE)
players.position.value_counts(dropna=False, ascending=True).plot(kind='barh', ax=ax)
ax.set_ylabel("Position")
ax.set_xlabel("Counts")
fig.tight_layout()

在这里插入图片描述位置信息有点多,可以将其集中划分为几类:

  • 位置种类
position_types = players.position.unique()
position_types

在这里插入图片描述

  • 将位置统一划分
  • isin()接受一个列表,判断该列中元素是否在列表中。
defense = ['Center Back','Defensive Midfielder', 'Left Fullback', 'Right Fullback', ]
midfield = ['Right Midfielder', 'Center Midfielder', 'Left Midfielder',]
forward = ['Attacking Midfielder', 'Left Winger', 'Right Winger', 'Center Forward']
keeper = 'Goalkeeper'

players.loc[players['position'].isin(defense), 'position_agg'] = "Defense"
players.loc[players['position'].isin(midfield), 'position_agg'] = "Midfield"
players.loc[players['position'].isin(forward), 'position_agg'] = "Forward"
players.loc[players['position'].eq(keeper), 'position_agg'] = "Keeper"
  • 画出分好位置的数量
MIDSIZE = (12, 8)
fig, ax = plt.subplots(figsize=MIDSIZE)
players['position_agg'].value_counts(dropna=False, ascending=True).plot(kind='barh', ax=ax)
ax.set_ylabel("position_agg")
ax.set_xlabel("Counts")
fig.tight_layout()

在这里插入图片描述

3.8 使用散点图矩阵图,可以两两发现特征之间的联系

  • 身高,体重,肤色的关系
from pandas.tools.plotting import scatter_matrix
fig, ax = plt.subplots(figsize=(10, 10))
scatter_matrix(players[['height', 'weight', 'skintone']], alpha=0.2, diagonal='hist', ax=ax);

在这里插入图片描述
可以看出,身高和体重与肤色并无明显关系

  • 体重和身高的关系散点图矩阵图
fig, ax = plt.subplots(figsize=MIDSIZE)
sns.regplot('weight', 'height', data=players, ax=ax)
ax.set_ylabel("Height [cm]")
ax.set_xlabel("Weight [kg]")
fig.tight_layout()

在这里插入图片描述
可以看出,体重和身高成线性相关

3.9 身高与体重划分

  • pd.qcut(df, len(), columns)
#身高
height_categories = ["vlow_height",
                     "low_height",
                     "mid_height",
                     "high_height",
                     "vhigh_height",
                    ]

players['heightclass'] = pd.qcut(players['height'],
                                 len(height_categories),
                                 height_categories)

#体重
weight_categories = ["vlow_weight",
                     "low_weight",
                     "mid_weight",
                     "high_weight",
                     "vhigh_weight",
                    ]

players['weightclass'] = pd.qcut(players['weight'],
                                 len(weight_categories),
                                 weight_categories)
players.head()                              

3.10 肤色划分

print (players['skintone'])
pd.qcut(players['skintone'], 3)
players['skintoneclass'] = pd.qcut(players['skintone'], 3)
players

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

4.报表可视化分析(Pandas profiling)

4.1 总体数据

  • 首先是数据集信息:
  • 变量数(列)、观察数(行)、数据缺失率、内存;
  • 数据类型的分布情况
    在这里插入图片描述

4.2 警告信息

在这里插入图片描述
在这里插入图片描述
详细信息:https://blog.csdn.net/weixin_43746433/article/details/97119966

5. 红牌和肤色的关系

问题——如何处理生日专栏?
需要考虑的几点:

  • 这是截至2012-2013赛季的一个职业生涯数据集
  • 2012年玩家的年龄(不一定)与收到红牌的日期相对应。

5.1 生日转年龄

players.birthday.head()

在这里插入图片描述

players['birth_date'] = pd.to_datetime(players.birthday, format='%d.%m.%Y')
players['age_years'] = ((pd.to_datetime("2013-01-01") - players['birth_date']).dt.days)/365.25 #润年+1/4
players['age_years']

在这里插入图片描述

5.2 划分的列的报表可视化分析(Pandas profiling)

players.head()

在这里插入图片描述

  • 所有列名
players_cleaned_variables = players.columns.tolist()
players_cleaned_variables

在这里插入图片描述

  • 可视化报表
players_cleaned_variables = [#'birthday',
                             'height',
                             'weight',
#                              'position',
#                              'photoID',
#                              'rater1',
#                              'rater2',
                             'skintone',
                             'position_agg',
                             'weightclass',
                             'heightclass',
                             'skintoneclass',
#                              'birth_date',
                             'age_years']
pandas_profiling.ProfileReport(players[players_cleaned_variables])

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

5.3 划分的列保存数据

players[players_cleaned_variables].to_csv("cleaned_players.csv.gz", compression='gzip')

6. 数据更多融合

6.1 裁判和球员信息

clean_players = load_subgroup("cleaned_players.csv.gz")
players = load_subgroup("raw_players.csv.gz", )
countries = load_subgroup("raw_countries.csv.gz")
referees = load_subgroup("raw_referees.csv.gz")
agg_dyads = pd.read_csv("raw_dyads.csv.gz", compression='gzip', index_col=[0, 1])

agg_dyads.head(10)

在这里插入图片描述

6.2 逻辑判断

  • 局数=胜场+平局+失败?
all(agg_dyads['games'] == agg_dyads.victories + agg_dyads.ties + agg_dyads.defeats)

在这里插入图片描述

6.3 数据融合

agg_dyads['totalRedCards'] = agg_dyads['yellowReds'] + agg_dyads['redCards']
agg_dyads.rename(columns={'redCards': 'strictRedCards'}, inplace=True)
agg_dyads.head()

在这里插入图片描述

clean_players.head()

在这里插入图片描述

agg_dyads.head()

在这里插入图片描述

agg_dyads.reset_index().head()

在这里插入图片描述

agg_dyads.reset_index().set_index('playerShort').head()

在这里插入图片描述

  • 合并agg_dyads与clean_players
clean_dyads = (agg_dyads.reset_index()[agg_dyads.reset_index()
                                   .playerShort
                                   .isin(set(clean_players.index))
                                  ]).set_index(['refNum', 'playerShort'])

在这里插入图片描述

6.4 查看裁判与球员与牌的数量

  • 裁判给牌数量
tidy_dyads.head()

在这里插入图片描述

(tidy_dyads.groupby(level=0)
           .sum()
           .sort_values('redcard', ascending=False)
           .rename(columns={'redcard':'total redcards given'})).head()

在这里插入图片描述

  • 球员被给牌数量
(tidy_dyads.groupby(level=1)
           .sum()
           .sort_values('redcard', ascending=False)
           .rename(columns={'redcard':'total redcards received'})).head()

在这里插入图片描述

6.5 肤色与各类的关系

tidy_dyads.groupby(level=1).sum().sort_values(ascending=False, by='redcard').head()

在这里插入图片描述

  • 合并
player_ref_game = (tidy_dyads.reset_index()
                               .set_index('playerShort')
                                       .merge(clean_players,
                                              left_index=True,
                                              right_index=True)
                  )
player_ref_game.head()

在这里插入图片描述

bootstrap = pd.concat([player_ref_game.sample(replace=True, 
                                              n=10000).groupby('skintone').mean() 
                       for _ in range(100)])
player_ref_game.sample(replace=True,n=10000).groupby('skintone').mean()                       

在这里插入图片描述

  • 绘图
ax = sns.regplot(bootstrap.index.values,
                 y='redcard',
                 data=bootstrap,
                 lowess=True,
                 scatter_kws={'alpha':0.4,},
                 x_jitter=(0.125 / 4.0))
ax.set_xlabel("Skintone");

在这里插入图片描述

  • 0
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
探索性数据分析是指在研究初期,通过对数据进行可视化和统计分析来发现数据之间的关系、趋势和异常情况的过程。而JMP软件是一款广泛应用于数据分析和建模的统计软件,可以帮助用户进行数据可视化、统计分析、模型建立和预测等工作。 在JMP软件中,所有的数据集可以通过以下几种方式找到: 1. 数据导入:用户可以直接将数据文件导入JMP软件,常见的数据文件格式包括CSV文件、Excel文件、数据库文件等。导入后的数据集将显示在JMP软件的数据管理器中,用户可以对数据集进行选择、查看和操作。 2. JMP示例数据集:JMP软件内置了丰富的示例数据集,用户可以通过打开“示例数据”选项来访问这些数据集。这些数据集涵盖了各种数据类型和应用场景,可以供用户进行实际操作和学习。 3. 分析报告中的数据集:在进行探索性数据分析时,用户可以通过设置不同的统计分析和图表可视化来生成分析报告。在分析报告中生成的数据集将保存在JMP软件中,用户可以直接访问和查看这些数据集,进一步进行分析和建模。 除了以上几种方式,用户还可以通过JMP软件提供的搜索功能来快速查找其他用户创建和共享的数据集。用户可以在JMP社区中搜索相关的关键词,例如“探索性数据分析”、“数据集”等,来寻找其他用户分享的数据集,以供进一步分析和学习。 总之,JMP软件提供了多种途径来获取和访问数据集,用户可以通过导入数据、使用示例数据集、分析报告中的数据集以及搜索其他用户分享的数据集来进行探索性数据分析。这些数据集将为用户提供丰富的数据资源,帮助他们进行数据分析和模型建立。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值