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
df = pd.read_csv("nba_2017_nba_players_with_salary.csv")
df.head()
df.describe()
df.columns
专业名词字段含义说明:
df.info()
为了便于理解,对列名称重命名
df.columns=['排名', '姓名', '位置', '年龄', '场均比赛时间', '场均投球命中数', '场均投射次数', '命中率', '三分球命中次数',
'三分球投射次数', '三分球命中率', '二分球命中次数', '二分球投射次数', '二分球命中率', '有效命中率', '罚球命中次数',
'罚球投射次数', '罚球命中率', '进攻篮板数','防守篮板数', '篮板球总数', '助攻', '抢断', '盖帽', '失误', '犯规次数',
'得分', '球队', '比赛场数','场均上场时间', '进攻正负值', '防守正负值', '正负值', '赢球正负值', '球员贡献度', '48分钟回合数',
'胜利次数','薪水']
df.head()
df.isnull().sum()
由df.isnull().sum()结果可知,缺失值‘三分球命中率’有22项,‘罚球命中率’有5项,下面显示缺失值的所在行
三分球命中率_null =df[df["三分球命中率"].isnull()==True]
罚球命中率_null =df[df["罚球命中率"].isnull()==True]
由上方数据显示,分析可得,3P%和FT%的数值空缺原因均是因为3P、3PA、FT和FTA数值为0导致,
为数据精准度,使用dropna()直接将所有含空缺值的数据行删除
df = df.dropna()
根据数据探测可知,数据集中有多为球员姓名重复,删除重复项并保留第一次出现的项
df[df.duplicated(subset=['姓名']).values == True]
df=df.drop_duplicates(subset=['姓名'], keep='first', inplace=False)
根据所查资料知,效率值最能反应球员对比赛做出的贡献
df['效率值']=((df['得分']+df['篮板球总数']+df['助攻']+df['抢断']+df['盖帽'])-(df['场均投射次数']-df['场均投球命中数'])-(df['罚球投射次数']-df['罚球命中次数'])-df['失误'])/df['比赛场数']
PER_array = np.array(df['效率值'])
PER_array
df = df.round(3) #保留3位小数
找出判断球员贡献度相关的数据,得到其中的数据相关性,并用相关系数矩阵显示,并使用热力图进行可视化
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')
# 按照球员贡献度排名
df.loc[:, ["姓名", "球员贡献度","薪水", "年龄","比赛场数"]].sort_values(by="球员贡献度", ascending=False).head()
# 按照场均上场时间排名
df.loc[:, ["姓名", "球员贡献度","薪水", "年龄","场均上场时间"]].sort_values(by="场均上场时间", ascending=False).head()
位置 = pd.DataFrame(df[ "位置" ].value_counts()).reset_index()
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")
根据数据可视化结果分析可知,球员贡献度是最能反映球员的综合实力的特征。
由df.describe()得到的数据,人为划分球员:
自定义方法进行划分并为方便后续进行分类,将此项转化为一维数组
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
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)
# 定义模型
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)
查看各个特征对球员贡献度的相关度,找出除了球员贡献度的其他影响因素
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))