实例:【基于机器学习的NBA球员信息数据分析与可视化】

文章目录

  • 一、项目任务
  • 二、代码实现及分析
    • 1. 导入模块
    • 2. 导入文件并对文件信息进行整体探测
    • 3. 数据预处理
      • 3.1 查看数据集信息
      • 3.2 数据清洗与转换
      • 3.3 数据去重
    • 4. 数据可视化
      • 4.1 数据相关性
      • 4.2 球员数据分析
    • 5. 基于逻辑回归的球员分类
      • 5.1 数据重定义
      • 5.2 划分数据集与验证集
      • 5.3 定义模型
    • 6. 基于随机森林回归模型的特征评分排序

一、项目任务

  • 数据集共有342个NBA球员样本,包含38个特征,即342行×38列。对这些数据进行集成和预处理。
  • 利用python语言,设计合适的机器学习算法。找出球员在场时对球队比赛获胜的贡献大小,最能反映球员的综合实力的特征。
  • 算法过程及结果的设计合适的可视化图像,将所设计的算法的过程,以及最终结果展示出来。

二、代码实现及分析

1. 导入模块

import pandas as pd
import numpy as np
import plotly.express as px
import matplotlib.pyplot as plt
import seaborn as sns

from sklearn.linear_model import LogisticRegression 
from sklearn.model_selection import train_test_split 
from sklearn.metrics import mean_squared_error
from sklearn import metrics
from sklearn.ensemble import RandomForestRegressor

plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
plt.rcParams['axes.unicode_minus'] = False

2. 导入文件并对文件信息进行整体探测

df = pd.read_csv("nba_2017_nba_players_with_salary.csv") 
df.head()

df.describe()


查看关键字:

df.columns

专业名词字段含义说明:

  • Rk:排名
  • PLAYER:姓名
  • POSITION:位置
  • AGE:年龄
  • MP:平均每场比赛进行的时间
  • FG:场均投球命中次数
  • FGA:场均投射次数
  • FG%:命中率
  • 3P:三分球命中次数
  • 3PA:三分球投射次数
  • 3P%:三分球命中率(命中次数/投射次数—-3P/3PA=3P%)
  • 2P:二分球命中次数
  • 2PA:二分球投射次数
  • 2P%:二分球命中率
  • eFG%:有效命中率
  • FT:罚球命中次数
  • FTA:罚球投射次数
  • FT%:罚球命中率(FT/FTA=FT%)
  • ORB:进攻篮板数
  • DRB:防守篮板数
  • TRB:篮板球总数

    篮板率=球员篮板数×(球队所有球员上场时间÷5)÷球员上场时间÷(球队总篮板+对手总篮板)
  • AST:助攻

    助攻率=球员助攻数÷(球员上场时间÷(球队所有球员上场时间÷5)×(球队总进球数-球员进球数)
  • STL:抢断

    抢断率=球员抢断数×(球队所有球员上场时间÷5)÷球员上场时间÷对手进攻次数
  • BLK:盖帽

    盖帽率=球员盖帽数×(球队所有球员上场时间÷5)÷球员上场时间÷对手两分球出手次数)
  • TOV:失误

    失误率=球员失误数÷(球员两分球出手次数+0.44×球员罚球次数+球员失误数)
  • PF:犯规次数
  • POINTS:得分
  • TEAM:球队
  • GP:比赛场数
  • MPG:场均上场时间
  • ORPM:进攻正负值
  • DRPM:防守正负值
  • RPM:正负值
  • WINS_RPM:赢球正负值
  • PIE:球员贡献度

    加分项:得分、投篮命中数、罚篮命中数、篮板、助攻、抢断、盖帽

    减分项:投篮出手、罚篮出手、个人犯规、失误
  • PACE:每48分钟内大概会进行多少个回合
  • W:胜利次数
  • SALARY_MILLIONS:薪水

3. 数据预处理

3.1 查看数据集信息

df.info()

3.2 数据清洗与转换

为了便于理解,对列名称重命名

df.columns=['排名', '姓名', '位置', '年龄', '场均比赛时间', '场均投球命中数', '场均投射次数', '命中率', '三分球命中次数',
        '三分球投射次数', '三分球命中率', '二分球命中次数', '二分球投射次数', '二分球命中率', '有效命中率', '罚球命中次数',
        '罚球投射次数', '罚球命中率', '进攻篮板数','防守篮板数', '篮板球总数', '助攻', '抢断', '盖帽', '失误', '犯规次数',
        '得分', '球队', '比赛场数','场均上场时间', '进攻正负值', '防守正负值', '正负值', '赢球正负值', '球员贡献度', '48分钟回合数', 
        '胜利次数','薪水']
df.head()

df.isnull().sum()

由df.isnull().sum()结果可知,缺失值‘三分球命中率’有22项,‘罚球命中率’有5项,下面显示缺失值的所在行

三分球命中率_null =df[df["三分球命中率"].isnull()==True]
罚球命中率_null =df[df["罚球命中率"].isnull()==True]

  • 3P%:三分球命中率——3P/3PA=3P%
  • FT%:罚球命中率——FT/FTA=FT%

由上方数据显示,分析可得,3P%和FT%的数值空缺原因均是因为3P、3PA、FT和FTA数值为0导致,
为数据精准度,使用dropna()直接将所有含空缺值的数据行删除

df = df.dropna()

3.3 数据去重

根据数据探测可知,数据集中有多为球员姓名重复,删除重复项并保留第一次出现的项

df[df.duplicated(subset=['姓名']).values == True]

df=df.drop_duplicates(subset=['姓名'], keep='first', inplace=False)

根据所查资料知,效率值最能反应球员对比赛做出的贡献

  • PER:效率值

    效率值=[(得分+篮板球总数+助攻+抢断+盖帽)-(场均投射次数-场均投球命中次数)-(罚球投射次数-罚球命中次数)-失误)]/比赛场数
df['效率值']=((df['得分']+df['篮板球总数']+df['助攻']+df['抢断']+df['盖帽'])-(df['场均投射次数']-df['场均投球命中数'])-(df['罚球投射次数']-df['罚球命中次数'])-df['失误'])/df['比赛场数']
PER_array = np.array(df['效率值'])
PER_array

df = df.round(3) #保留3位小数

4. 数据可视化

4.1 数据相关性

找出判断球员贡献度相关的数据,得到其中的数据相关性,并用相关系数矩阵显示,并使用热力图进行可视化

df_cor = df.loc[:, [ '命中率',  '三分球命中率', '二分球命中率', '有效命中率','罚球命中率', 
                    '篮板球总数', '助攻', '抢断', '盖帽', '失误', '犯规次数','得分', 
                    '比赛场数','场均上场时间', '赢球正负值', '球员贡献度','防守正负值', '胜利次数','薪水']]
                    
#调用corr()方法 获取两列数据之间的相关性
# 返回改数据类型的相关系数矩阵(即每两个类型直接的相关性)
corr = df_cor.corr()
corr.head()


使用热力图呈现:

plt.figure(figsize=(20,8),dpi=100)
sns.heatmap(corr,square=True,linewidths=0.1,annot=True,cmap='Accent')

4.2 球员数据分析

# 按照球员贡献度排名
df.loc[:, ["姓名", "球员贡献度","薪水", "年龄","比赛场数"]].sort_values(by="球员贡献度", ascending=False).head()

# 按照场均上场时间排名
df.loc[:, ["姓名", "球员贡献度","薪水", "年龄","场均上场时间"]].sort_values(by="场均上场时间", ascending=False).head()

位置 = pd.DataFrame(df[ "位置" ].value_counts()).reset_index()


位置名词解释:

  • PG:控卫
  • SG:分卫
  • PF:大前
  • SF:小前
  • C:中锋
fig=px.pie(位置,names="index" ,values="位置")
fig.show ()


查看各个站位的球员薪水分布:

price = (df.groupby("位置")["薪水"].mean().reset_index().sort_values( "薪水").reset_index(drop=True))
fig =px.bar_polar(price,theta="位置",color='薪水',color_discrete_sequence=px.colors.sequential.Plasma_r,template='plotly_white')
fig.show()

fig = px.scatter(df,x='球员贡献度',y="排名",color='球员贡献度')
fig.show()

小结: 球员贡献度越高排名越高

查看排名和薪水的关系:

fig = px.scatter(df,x='排名',y="薪水",color='排名')
fig.show()

小结: 排名越低薪水越低

#用pairplot() 方法 进行数据对比
sns.pairplot(df,vars=['排名','球员贡献度','比赛场数','命中率','得分'], diag_kind="kde")

5. 基于逻辑回归的球员分类

5.1 数据重定义

根据数据可视化结果分析可知,球员贡献度是最能反映球员的综合实力的特征。
由df.describe()得到的数据,人为划分球员:

  • 球员贡献度 <= 7.2 标记为0,记作表现不合格
  • 球员贡献度 <= 9.31标记为1,记作表现合格
  • 球员贡献度 <= 15 标记为2,记作表现良好
  • 球员贡献度 <= 23 标记为3,记作表现优秀

自定义方法进行划分并为方便后续进行分类,将此项转化为一维数组
def 球员贡献度_cut(df):
    if df.球员贡献度 <= 7.2:
        return 0  #不合格
    elif df.球员贡献度 <=9.31:
        return 1  # 合格
    elif df.球员贡献度 <=15:
        return 2  # 良好
    else:
        return 3  # 优秀

df['球员贡献度_cut']=df.apply(lambda x:球员贡献度_cut(x),axis=1)
print(df['球员贡献度_cut'])
Pie1_array = np.array(df['球员贡献度_cut'])
Pie1_array

5.2 划分数据集与验证集

df_new = df.drop(columns=["姓名", "位置","球队"]) # 去除非数值型数据
X_train,X_test,Y_train,Y_test=train_test_split(df_new,Pie1_array,test_size=0.2,random_state=180)

5.3 定义模型

# 定义模型
def basic_logosticregression(X_train,X_test,Y_train,Y_test):
    model=LogisticRegression(random_state=0, solver='lbfgs')
    model.fit(X_train,Y_train)
    
    Y_train_pre=model.predict(X_train)
    Y_test_pre=model.predict(X_test)
    
    train_predict_proba = model.predict_proba(X_train)
    test_predict_proba = model.predict_proba(X_test)

    confusion_matrix_result = metrics.confusion_matrix(Y_test_pre,Y_test)
    
    print('混淆矩阵结果:\n',confusion_matrix_result)
    plt.figure(figsize=(8, 6))
    sns.heatmap(confusion_matrix_result, annot=True, cmap='Blues')
    
    plt.xlabel('预测的标签')
    plt.ylabel('实际的标签')
    
    print("score_train: "+str(model.score(X_train, Y_train)))
    print("score_test: "+str(model.score(X_test,Y_test)))  

调用:

basic_logosticregression(X_train,X_test,Y_train,Y_test)


6. 基于随机森林回归模型的特征评分排序

查看各个特征对球员贡献度的相关度,找出除了球员贡献度的其他影响因素

Pie_array = np.array(df['球员贡献度'])
df_new = df.drop(columns=["姓名", "位置","球队",'球员贡献度'])
data=df_new.values.tolist()

X = data
Y = Pie_array
feature_names=['排名', '年龄', '场均比赛时间', '场均投球命中数', '场均投射次数', '命中率','三分球命中次数',
               '三分球投射次数', '三分球命中率', '二分球命中次数', '二分球投射次数', '二分球命中率', '有效命中率',
               '罚球命中次数','罚球投射次数', '罚球命中率', '进攻篮板数','防守篮板数', '篮板球总数', '助攻',
               '抢断', '盖帽','失误', '犯规次数','得分', '比赛场数','场均上场时间','进攻正负值', '防守正负值',
               '正负值', '赢球正负值', '48分钟回合数','胜利次数','薪水']

names = feature_names

rf = RandomForestRegressor()
rf.fit(X, Y)
print("特征评分排序:")
print(sorted(zip(map(lambda x: round(x, 4), rf.feature_importances_), names),reverse=True))

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
青葱年少的头像青葱年少普通用户
上一篇 2023年6月16日
下一篇 2023年6月16日

相关推荐