(一)选题背景:NBA 作为世界上水平最高的篮球联赛,吸引了无数的球迷。每一场NBA 比赛都会产生大量的数据信息,如果能够有效地运用这些数据,便可以充分发挥出其潜在价值。
在每年赛季开始之前,大量的媒体专家都会对本赛季 NBA 常规赛的情况进行预测,这其中球队战绩和明星球员的个人数据是大家着重讨论的话题。及时而准确的完成对这些数据的预测一方面有利于各球队管理层在赛季进行前采用合适的决策,另一方面可以最大化商业公司的利益。本实验在赛季开始前完成对本赛季 NBA 球队战绩以及个人数据的分析。
(二)大数据分析方案:从网站中下载相关的数据集,对数据集进行整理,在python的环境中,给数据集中的文件打上标签,对数据进行预处理,利用keras,构建网络,训练模型,导入图片测试模型。
(三)数据分析的实现步骤:
1.导入相关库
[1]
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns;sns.set()
%matplotlib inline
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import KFold
2.读取数据集CSV
[2]
Butler = pd.read_csv('Butler_data.csv')
Butler.head(4)
action_typecombined_shot_typegame_event_idgame_idlatloc_xloc_ylonminutes_remainingperiod...shot_typeshot_zone_areashot_zone_basicshot_zone_rangeteam_idteam_namegame_datematchupopponentshot_id0Jump ShotJump Shot102000001233.972316772-118.1028101...2PT Field GoalRight Side(R)Mid-Range16-24 ft.1610612747Los Angeles Lakers2000-10-31LAL @ PORPOR11Jump ShotJump Shot122000001234.0443-1570-118.4268101...2PT Field GoalLeft Side(L)Mid-Range8-16 ft.1610612747Los Angeles Lakers2000-10-31LAL @ PORPOR22Jump ShotJump Shot352000001233.9093-101135-118.370871...2PT Field GoalLeft Side Center(LC)Mid-Range16-24 ft.1610612747Los Angeles Lakers2000-10-31LAL @ PORPOR33Jump ShotJump Shot432000001233.8693138175-118.131861...2PT Field GoalRight Side Center(RC)Mid-Range16-24 ft.1610612747Los Angeles Lakers2000-10-31LAL @ PORPOR4
3.数据集清洗和预处理
[3]
Butler.describ()
[4]
Butler.shape#处理前总共有30697个数据
(30697, 25)
[5]
Butler = Butler[pd.notnull(Butler['shot_made_flag'])]#通过以上数据集的列举对空值进行处理
Butler.describe()
[6]
Butler.shape#处理后则使用25697个有用数据
(25697, 25)
[7]
Butler.info()#该数据集共有0-24也就是25个特征
4.数据探索性分析
4.1单变量分析
[8]
plt.rcParams['font.sans-serif']=['SimHei']#防止中文标签报错
plt.rcParams['axes.unicode_minus']=False#防止负号报错
#查看巴特勒出手类型的分布
plt.figure(figsize = (10,6))
Butler['combined_shot_type'].value_counts().plot(kind = 'bar')
plt.xlabel('出手类型');plt.ylabel('出手次数');plt.title('吉米.巴特勒职业生涯不同出手类型的次数统计')
Text(0.5, 1.0, '吉米.巴特勒职业生涯不同出手类型的次数统计')
[9]
#查看巴特勒两分球,三分球的出手数
plt.figure(figsize = (8,6))
Butler['shot_type'].value_counts().plot(kind = 'bar')
plt.xlabel('远投还是中距离');plt.ylabel('出手次数');plt.title('吉米.巴特勒职业生涯远投和中距离的出手数')
plt.xticks(rotation = 0)
(array([0, 1]), [Text(0, 0, '2PT Field Goal'), Text(1, 0, '3PT Field Goal')])
[10]
#查看巴特勒出手距离的分布
plt.figure(figsize = (8,6))
Butler['shot_distance'].hist(bins = 100)
plt.xlabel('出手距离');plt.ylabel('出手次数');plt.title('吉米.巴特勒出手距离的分布')
Text(0.5, 1.0, '吉米.巴特勒出手距离的分布')
[11]
#绘制箱型图
plt.figure(figsize = (6,4))
sns.boxplot(data = Butler,y = 'shot_distance')
plt.xlabel('出手距离');plt.ylabel('出手次数');plt.title('吉米.巴特勒出手距离的分布')
Text(0.5, 1.0, '吉米.巴特勒出手距离的分布')
[12]
#可视化巴特勒的出手区域,按照不同的标准划分的出手区域
import matplotlib.cm as cm
plt.figure(figsize = (20,10))
def scatter_plot_by_category(feat):
alpha = 0.1
gs = Butler.groupby(feat)
cs = cm.rainbow(np.linspace(0,1,len(gs)))
for g,c in zip(gs,cs):
plt.scatter(g[1].loc_x,g[1].loc_y,color = c,alpha = alpha)
plt.subplot(1,3,1)
scatter_plot_by_category(Butler['shot_zone_area'])
plt.title('shot_zone_area')
plt.subplot(1,3,2)
scatter_plot_by_category(Butler['shot_zone_basic'])
plt.title('shot_zone_basic')
plt.subplot(1,3,3)
scatter_plot_by_category(Butler['shot_zone_range'])
plt.title('shot_zone_range')
Text(0.5, 1.0, 'shot_zone_range')
[13]
Butler['shot_distance'].describe()#各距离投射占比
count 25697.000000
mean 13.457096
std 9.388725
min 0.000000
25% 5.000000
50% 15.000000
75% 21.000000
max 79.000000
Name: shot_distance, dtype: float64
mean 13.457096
std 9.388725
min 0.000000
25% 5.000000
50% 15.000000
75% 21.000000
max 79.000000
Name: shot_distance, dtype: float64
[14]
#巴特勒在各个位置投篮的次数
area = Butler['shot_zone_basic'].value_counts()
b = np.array([0,1,2,3,4,5,6])
plt.barh(b,area,align ='center')
plt.yticks(b,('中距离','进攻有理区','底线之外的三分','除进攻有理区外的禁区','右边底线三分','左边底线三分','后场'))
plt.xlabel('次数',fontsize=10)
plt.title('吉米.巴特勒在各区域投篮次数',fontsize=20)
plt.tight_layout()# 紧凑显示图片,居中显示
plt.show()
4.2双变量分析
[15]
#查看巴特勒的出手命中率
plt.figure(figsize = (6,4))
Butler['shot_made_flag'].value_counts(normalize = True).plot(kind = 'bar')
plt.xlabel('命中情况');plt.ylabel('命中个数');plt.title('吉米.巴特勒的出手命中率')
Text(0.5, 1.0, '吉米.巴特勒的出手命中率')
[16]
#观察不同出手类型与命中率之间的关系
sns.barplot(data = Butler,x = 'combined_shot_type',y = 'shot_made_flag')
<AxesSubplot:xlabel='combined_shot_type', ylabel='shot_made_flag'>
[17]
#观察两分球与三分球的命中率
sns.barplot(data = Butler,x = 'shot_type',y = 'shot_made_flag')
<AxesSubplot:xlabel='shot_type', ylabel='shot_made_flag'>
[18]
#观察出手距离与命中率之间的关系
sns.scatterplot(data = Butler, x = 'shot_distance',y = 'shot_made_flag' )
<AxesSubplot:xlabel='shot_distance', ylabel='shot_made_flag'>
[19]
sns.violinplot(data = Butler, y = 'shot_distance',x = 'shot_made_flag' )
<AxesSubplot:xlabel='shot_made_flag', ylabel='shot_distance'>
5.完整代码
1 import numpy as np 2 import pandas as pd 3 import matplotlib.pyplot as plt 4 import seaborn as sns;sns.set() 5 %matplotlib inline 6 7 from sklearn.ensemble import RandomForestClassifier 8 from sklearn.model_selection import KFold 9 94 # 查看前三行 95 96 year_df[2019].head(3) 97 98 for i in range(2014, 2020): 99 100 year_df[i] 101 102 # 删除以下列 103 104 del_name = ['pid','tid','games_played','games_started','points'] 105 106 year_df[i] = year_df[i].drop(del_name,axis=1) 107 108 # 连接first_name和last_name 109 110 year_df[i]['player_name'] = year_df[i]['first_name']+"-"+year_df[i]['last_name'] 111 112 player_name = year_df[i].player_name 113 114 year_df[i] = year_df[i].drop(['first_name','last_name'],axis=1) 115 116 year_df[i] = year_df[i].drop('player_name',axis=1) 117 118 # 将player_name插入到第二列 119 120 year_df[i].insert(1,'player_name',player_name) 121 122 team_name = df.team_name 123 124 year_df[i] = year_df[i].drop('team_name',axis=1) 125 126 # 将team_name插入到第三列 127 128 year_df[i].insert(2,'team_name',team_name) 129 130 year_df[2019].columns 131 132 Index(['rank', 'player_name', 'team_name', 'score', 'minutes', 133 134 'field_goals_made', 'field_goals_att', 'field_goals_pct', 135 136 'three_points_made', 'three_points_att', 'three_points_pct', 137 138 'free_throws_made', 'free_throws_att', 'free_throws_pct', 139 140 'offensive_rebounds', 'defensive_rebounds', 'rebounds', 'assists', 141 142 'turnovers', 'assists_turnover_ratio', 'steals', 'blocks', 143 144 'personal_fouls'], 145 146 dtype='object') 147 148 # 查看前三行 149 150 year_df[2019].head(3) 151 152 # info方法可以显示每列名称,非空值数量,每列的数据类型,内存占用等信息。 153 154 # data.info() 155 156 for i in range(2014, 2019): 157 158 print("============"+str(i)+"年============") 159 160 print(year_df[i].isnull().sum(axis=0)) 161 162 # 删除所有含有空值的行。就地修改。 163 164 # year_df[2019].dropna(axis=0, inplace=True) 165 166 # year_df[2019].isnull().sum() 167 168 year_df[2019].describe() 169 170 # 箱型图 171 172 plt.figure(figsize=(15, 8)) 173 174 df = year_df[2019].iloc[:, 3:].copy() 175 176 col_name_fe = [] 177 178 col_name_yi = dict() 179 180 i = 0 181 182 for item in df.columns.values: 183 184 temp = (item[0] + item[1] + item[-2]).upper() 185 186 col_name_fe.append(temp) 187 188 col_name_yi[temp.upper()] = item 189 190 i += 1 191 192 df.columns = col_name_fe 193 194 # whitegrid,darkgrid 195 196 sns.set_style("whitegrid") 197 198 sns.boxplot(data=df[list(df.columns)]) 199 200 print(col_name_yi) 201 202 year_df[2019].duplicated().sum() 203 204 # data.drop_duplicates(inplace=True) 205 206 Butler = pd.read_csv('Butler_data.csv') 207 208 Butler.head(4) 209 Butler.describe() 210 Butler.shape#处理前总共有30697个数据 211 (30697, 25) 212 Butler = Butler[pd.notnull(Butler['shot_made_flag'])]#通过以上数据集的列举对空值进行处理 213 Butler.describe() 214 Butler.shape#处理后则使用25697个有用数据 215 (25697, 25) 216 Butler.info()#该数据集共有0-24也就是25个特征 217 plt.rcParams['font.sans-serif']=['SimHei']#防止中文标签报错 218 plt.rcParams['axes.unicode_minus']=False#防止负号报错 219 #查看巴特勒出手类型的分布 220 plt.figure(figsize = (10,6)) 221 Butler['combined_shot_type'].value_counts().plot(kind = 'bar') 222 plt.xlabel('出手类型');plt.ylabel('出手次数');plt.title('吉米.巴特勒职业生涯不同出手类型的次数统计') 223 #查看巴特勒两分球,三分球的出手数 224 plt.figure(figsize = (8,6)) 225 Butler['shot_type'].value_counts().plot(kind = 'bar') 226 plt.xlabel('远投还是中距离');plt.ylabel('出手次数');plt.title('吉米.巴特勒职业生涯远投和中距离的出手数') 227 plt.xticks(rotation = 0) 228 #查看巴特勒出手距离的分布 229 plt.figure(figsize = (8,6)) 230 Butler['shot_distance'].hist(bins = 100) 231 plt.xlabel('出手距离');plt.ylabel('出手次数');plt.title('吉米.巴特勒出手距离的分布') 232 #绘制箱型图 233 plt.figure(figsize = (6,4)) 234 sns.boxplot(data = Butler,y = 'shot_distance') 235 plt.xlabel('出手距离');plt.ylabel('出手次数');plt.title('吉米.巴特勒出手距离的分布') 236 #可视化巴特勒的出手区域,按照不同的标准划分的出手区域 237 import matplotlib.cm as cm 238 plt.figure(figsize = (20,10)) 239 240 def scatter_plot_by_category(feat): 241 alpha = 0.1 242 gs = Butler.groupby(feat) 243 cs = cm.rainbow(np.linspace(0,1,len(gs))) 244 for g,c in zip(gs,cs): 245 plt.scatter(g[1].loc_x,g[1].loc_y,color = c,alpha = alpha) 246 247 plt.subplot(1,3,1) 248 scatter_plot_by_category(Butler['shot_zone_area']) 249 250 plt.title('shot_zone_area') 251 252 plt.subplot(1,3,2) 253 scatter_plot_by_category(Butler['shot_zone_basic']) 254 plt.title('shot_zone_basic') 255 256 plt.subplot(1,3,3) 257 scatter_plot_by_category(Butler['shot_zone_range']) 258 plt.title('shot_zone_range') 259 Butler['shot_distance'].describe()#各距离投射占比 260 #巴特勒在各个位置投篮的次数 261 area = Butler['shot_zone_basic'].value_counts() 262 b = np.array([0,1,2,3,4,5,6]) 263 plt.barh(b,area,align ='center') 264 plt.yticks(b,('中距离','进攻有理区','底线之外的三分','除进攻有理区外的禁区','右边底线三分','左边底线三分','后场')) 265 plt.xlabel('次数',fontsize=10) 266 plt.title('吉米.巴特勒在各区域投篮次数',fontsize=20) 267 plt.tight_layout()# 紧凑显示图片,居中显示 268 plt.show() 269 #查看巴特勒的出手命中率 270 plt.figure(figsize = (6,4)) 271 Butler['shot_made_flag'].value_counts(normalize = True).plot(kind = 'bar') 272 plt.xlabel('命中情况');plt.ylabel('命中个数');plt.title('吉米.巴特勒的出手命中率') 273 #观察不同出手类型与命中率之间的关系 274 275 sns.barplot(data = Butler,x = 'combined_shot_type',y = 'shot_made_flag') 276 #观察两分球与三分球的命中率 277 278 sns.barplot(data = Butler,x = 'shot_type',y = 'shot_made_flag') 279 #观察出手距离与命中率之间的关系 280 sns.scatterplot(data = Butler, x = 'shot_distance',y = 'shot_made_flag' ) 281 sns.violinplot(data = Butler, y = 'shot_distance',x = 'shot_made_flag' )