作者:鲁伟
一个数据科学践行者的学习日记。数据挖掘与机器学习,R与Python,理论与实践并行。个人公众号:数据科学家养成记 (微信ID:louwill12)
作为数据科学领域的金字招牌,kaggle已成为世界上最受欢迎的数据科学竞赛平台。在kaggle上,每个竞赛题下都藏匿着大批来自世界各地并且身怀绝技的数据科学家。作为一种众包模式,kaggle通过收取部分佣金将企业的数据挖掘问题发布在平台上并设立高额奖金来吸引数据科学家来解决。每位注册参加的kaggler都可以自由获取竞赛题目和数据集,并将自己的数据分析方案以报告的形式呈现在平台上供大家讨论,最后被企业方采用的数据分析方案的参赛者将会获得一大笔奖金。
鉴于目前小编的水平,不敢贸然去参赛,生怕做出来的结果排名垫底,于是盘算着先拿几个kaggle题的数据集来练手,一方面锻炼自己的数据思维和分析能力,另一方面则是提升R或者Python的coding能力。小编这次拿来练手的数据集叫做 NBA shot log.csv(公众号后台回复“NBA”下载数据),该数据集包括了2014-15赛季NBA30支球队904场常规赛281名球员将近13万的投篮数据,数据包括比赛双方、主客场、胜负情况、投篮球员、防守球员、投篮距离、命中次数等21个变量,可自由根据分析目的来进行数据挖掘建模。小编经过几天的探索,结合了kaggle上一干数据大神们的分析方案,决定分两篇推文展现对该数据集的分析挖掘。本文主要给大家展现对该数据集的探索性数据分析(EDA)和可视化,下篇将对数据拟合一些机器学习算法来预测球员们的投篮命中率情况。kaggle中 NBA shot log.csv的界面如下:
作为一名既热爱数据分析又看了十几年球的小编而言,不得不说NBA的数据实在是太适合拿来做分析了。经常看球的JRs们或许知道,休斯顿火箭队总经理莫雷就迷信一套篮球数据分析理论,坚信在数据的支撑下做出的决策是最好的决策。今年金州勇士队的夺冠和火箭成功杀入西部次轮无疑给莫雷的魔球理论提供了最好的事实证明。本篇虽然是做探索性数据分析和可视化,但无疑在分析之前我们需要拟定几个分析目标:
  • 现今NBA球员们的投篮选择有何偏好?
  • 球员们的投篮命中率都与哪些因素相关?
  • 主客场真的对球员表现、球队胜负有那么大影响吗?
  • 现今联盟里有哪些关键先生?
  • 哪些球员防守好,哪些球员防守差?
下面我们就根据上面五大目标来用
R语言
对数据集做探索性数据分析与可视化。

 读入数据后简单看一波数据概况:
nba_shots<-read.csv("shot_logs.csv")

dim(nba_shots) #数据量

[1] 128069 21

str(nba_shots) #数据结构

Classes ‘tbl_df’, ‘tbl’ and 'data.frame': 128069 obs. of 21 variables:

$ GAME_ID : int 21400899 21400899 21400899 21400899 21400899 21400899 21400899 21400899 21400899 21400890 ...

$ MATCHUP : Factor w/ 1808 levels "DEC 01, 2014 - DEN @ UTA",..: 1291 1291 1291 1291 1291 1291 1291 1291 1291 1277 ...

$ LOCATION : Factor w/ 2 levels "A","H": 1 1 1 1 1 1 1 1 1 2 ...

$ W  : Factor w/ 2 levels "L","W": 2 2 2 2 2 2 2 2 2 2 ...

$ FINAL_MARGIN : int 24 24 24 24 24 24 24 24 24 1 ...

$ SHOT_NUMBER : int 1 2 3 4 5 6 7 8 9 1 ...

$ PERIOD : int 1 1 1 2 2 2 4 4 4 2 ...

$ GAME_CLOCK : Factor w/ 719 levels "0:00","0:01",..: 70 15 1 228 155 615 136 600 434 213 ...

$ SHOT_CLOCK : num 10.8 3.4 NA 10.3 10.9 9.1 14.5 3.4 12.4 17.4 ...

$ DRIBBLES : int 2 0 3 2 2 2 11 3 0 0 ...

$ TOUCH_TIME : num 1.9 0.8 2.7 1.9 2.7 4.4 9 2.5 0.8 1.1 ...

$ SHOT_DIST : num 7.7 28.2 10.1 17.2 3.7 18.4 20.7 3.5 24.6 22.4 ...

$ PTS_TYPE : int 2 3 2 2 2 2 2 2 3 3 ...

$ SHOT_RESULT : Factor w/ 2 levels "made","missed": 1 2 2 2 2 2 2 1 2 2 ...

$ CLOSEST_DEFENDER : Factor w/ 473 levels "Acy, Quincy",..: 15 51 51 62 471 456 219 351 314 132 ...

$ CLOSEST_DEFENDER_PLAYER_ID: int 101187 202711 202711 203900 201152 101114 101127 203486 202721 201961 ...

$ CLOSE_DEF_DIST : num 1.3 6.1 0.9 3.4 1.1 2.6 6.1 2.1 7.3 19.8 ...

$ FGM  : int 1 0 0 0 0 0 0 1 0 0 ...

$ PTS  : int 2 0 0 0 0 0 0 2 0 0 ...

$ player_name : Factor w/ 281 levels "aaron brooks",..: 36 36 36 36 36 36 36 36 36 36 ...

$ player_id  : int 203148 203148 203148 203148 203148 203148

加载分析所需要的R包,本篇我们主要用到数据处理包dplyr以及可视化包ggplot2。

library(dplyr)

library(ggplot2)
1
球员们的投篮选择
现今NBA流行小球战术,强化三分球和内线突破而弱化中距离出手,我们通过数据分析来看看球员们投篮出手选择问题 ,选取投篮距离SHOT_DIST和防守人距离CLOSE_DEF_DIST等变量。先看球员们的出手距离分布:
ggplot(nba_shots,aes(SHOT_DIST))+geom_histogram()

由投篮距离的直方图分布可见,现今球员的投篮距离是个双峰分布,容易解释的是球员们在投篮上更偏向于冲击篮下突破或者选择三分线外发炮,而中距离出手明显较少,禁区内距离为0~10英尺,三分线为22英尺,由图中看明显符合这一趋势。再来看球员出手投篮时防守人的位置分布:
ggplot(nba_shots,aes(CLOSE_DEF_DIST))+geom_histogram()+ xlim(0,20)
从防守人位置分布图中可以看出,大多数投篮发生时防守人并未完全失位,5英尺以内防守人对投篮球员都有足够的威胁,只有少数快攻发生时防守球员不在位置而放弃防守,一方面可见NBA比赛强度可观,另一方面也体现了NBA球员们的技战术水平。
2
球员的命中率和哪些因素有关
熟悉篮球的JRs们一定清楚,球场上防守强度的高低决定了对手的投篮命中率,我们来看看NBA球员们的命中率都与哪些因素相关。选取投篮距离SHOT_DIST、防守人距离CLOSE_DEF_DIST、投篮结果SHOT_RESULT、运球次数DRIBBLES以及触球时间TOUCH_TIME等变量:
ggplot(nba_shots,aes(SHOT_DIST, CLOSE_DEF_DIST))+

     geom_point(aes(color=factor(SHOT_RESULT)))+

     geom_vline(xintercept=c(15,22),color="blue")

由上图可以看出,命中次数在近篮筐出有一个垂直分布,而防守人也不知所踪,这是由于防守反击造成的快攻上篮或者扣篮而通常防守人还在后场早已放弃防守所致,我们在罚球线距离(15英尺)和三分线距离(22英尺)出画了两条蓝线,篮下到罚球线距离之间明显有一个低谷,这也反映了当前在NBA球队里中距离投篮不受重视,而三分线附件则有一个投篮的密集分布,各支球队在三分线上的攻防也做足文章,显然,在大量的三分球战术下,各支球队在三分线外的命中率仍然不高。当然了,整体命中率依然是从篮下到三分线逐渐下降的分布趋势。

再看球员的运球次数、触球时间与命中投篮之间的关系:
ggplot(nba_shots,aes(DRIBBLES,TOUCH_TIME))+

   geom_point(aes(color=factor(SHOT_RESULT)))+ylim(-10,20)
容易看出的是,球员的投篮命中率与运球次数、触球时间并没有明显相关关系,接球就投(零运球)的情况下NBA球员通常都有一个较高的命中率,这一点也容易解释,通常战术跑出来后,某位球员出现空位的几率比较大,无论是三分球远射还是飞起扣篮,命中率都是极高的。在长时间运球与触球的情形下,虽然防守人能做好针对性防守,但此时一般球星都能通过运球找到节奏,再想防住他们的投篮困难就比较大了。参考詹姆斯.哈登和斯蒂芬.库里。而运球此时与触球时间则是明显的正相关关系。
3
主客场对球员表现和球队输赢影响大吗
事实上,主客场的影响确实大,小编看了15年NBA几乎所有球队的统计数据在客场和主场都有一个明显的差距,当然,我是说勇士和马刺这样的球队除外,毕竟宇宙勇强大到可以无视客场环境的存在的地步。还是拿数据说话,这里我们选取的变量包括主客场 LOCATION、投篮命中次数FGM以及通过FGM来构造命中率这个变量,采用dplyr包动词函数和管道操作符号来处理:
(home_away<-nba_shots %>% group_by(LOCATION) %>%

    summarise(PERCENTAGE=sum(FGM)/length(FGM)*100))

    LOC   PER
               1

              客场         44.8117
               2              主场
         45.6173

从数据分析的结果来看,主客场球队的命中率并无显著差别,但就这0.8个投篮百分点的差异足以让胜负翻转,且看主客场球队的胜负对比:
wins<-nba_shots %>% group_by(GAME_ID,LOCATION) %>% filter(W=='W',FGM

 ==1)

ggplot(data=wins,aes(LOCATION,fill=factor(W)))+geom_bar()

一对比到输赢上,差了几千场胜利啊!
4
现今联盟里有哪些关键先生
先看第一节比赛里都有哪些得分能手。通过dplyr里面的filter函数筛选出PERIOD==1,SHOT_DIST>5,然后用group_by对球员姓名进行数据分组,summarise函数归纳技术统计,mutate函数变形数据框将命中率变量加入,arrange函数对变量重排降序处理,一个问题我们几乎用了dplyr的所有动词函数:
first_quarter_guys<-nba_shots %>% filter(PERIOD==1,SHOT_DIST>5) %>%

 group_by(player_name) %>%

 summarise(made=sum(FGM),

  points=sum(PTS),

  total_attempts=length(FGM),

  ave_touch=mean(TOUCH_TIME),

  ave_distance=mean(SHOT_DIST)) %>%

mutate(percentage=made/total_attempts) %>%

arrange(desc(percentage)) %>% filter(total_attempts>200)

best_1st<-data.frame(first_quarter_guys)
第一节大神们出炉:

第一节得分最多的是JJ.雷迪克?这跟快船队的战术有关啦,第一节的比赛保罗和全队都是找雷迪克的,各种三分出手。

如果说先赢不叫赢,第一节得分不关键的话,我们再来看看在决定球队胜负的第四节,联盟中又有哪些关键先生呢。同样的处理方法:
fourth_quarter_guys<-nba_shots %>% filter(PERIOD==4,SHOT_DIST>5) %>%

group_by(player_name) %>%

  summarise(made=sum(FGM),

points=sum(PTS),

  total_attempts=length(FGM),

  ave_touch=mean(TOUCH_TIME),

  ave_distance=mean(SHOT_DIST)) %>%

mutate(percentage=made/total_attempts) %>%

arrange(desc(percentage)) %>% filter(total_attempts > 150)

best_4th<-data.frame(fourth_quarter_guys)
关键先生出炉!

两年前的韦斯利.马修斯是联盟头号第四节大腿!彼时的波特兰有利拉德、阿德、巴图姆、洛佩斯和马修斯为核心的首发阵容,强的不要不要的。保罗、詹姆斯、哈登、德克、韦德、贾马尔.克劳福德这些都是联盟成名已久的球星啦。顺便说一句,路威两年前就是路爸爸了。
5
最好、最差的防守球员是谁
同样是dplyr包的方法,这个实在太好用、太强大有没有!筛选、分组、归纳、重排,先来看看NBA里面最好的防守者有哪些:

nba_shots %>%

filter(SHOT_RESULT=="missed") %>%

group_by(CLOSEST_DEFENDER) %>%

summarise(GoodDefense = n()) %>%

ungroup %>%

arrange(desc(GoodDefense)) %>%

head

 DEFENDERGoodDefens
               1
 塞吉.伊巴卡

             480

               2
德拉蒙德.格林

             450
               3
德安德鲁.乔丹

             414
               4 保罗.加索尔
             400

               5保罗.米尔萨普             393
               6
 马辛.戈塔特

             386
清一色的内线球员哈,毕竟内线球员的防守数据(篮板+封盖)可以直观量化。雷霆时期伊巴卡的封盖真不是吹的。

再看哪些球员防守比较差了:
nba_shots %>%

   filter(SHOT_RESULT=="made") %>%

   group_by(CLOSEST_DEFENDER) %>%

   summarise(BadDefense = n()) %>%

   ungroup %>%

   arrange(desc(BadDefense)) %>%

   head

  DEFENDER
   BadDefens
               1
德安德鲁.乔丹

             381

               2保罗.米尔萨普             357
               3
 钱宁.弗莱

             355
               4
 保罗.加索尔

             354

               5
 武切维奇

             335
               6
 迪恩

             334
小乔丹:说我防守好的是你,说我防守差的也是你!说好的数据说话呢?

哈哈,这里我们只是单一指标来衡量防守,所以评估还是相当不成熟的,在NBA里防守数据很难量化,现在专业的NBA数据分析师有各种进阶数据来衡量一名球员的防守数据,我们这里只供参考,重在数据分析过程哈。
kaggle上这个关于NBA的13万的数据集里面还有太多值得分析和探索的内容,小编在这里也仅仅是选取了几个自己感兴趣的方面进行了分析,更多的方面需要大家自己去挖掘,下一篇小编会在此基础上做一些特征选择与构造以及机器学习算法建模。数据分析与数据挖掘,Practice make perfect !

公众号后台回复关键字即可学习
回复 
R
              R语言快速入门免费视频 

回复 
统计
          统计方法及其在R中的实现

回复 
用户画像
   民生银行客户画像搭建与应用 

回复 
大数据
      大数据系列免费视频教程

回复 
可视化
      利用R语言做数据可视化

回复 
数据挖掘
   数据挖掘算法原理解释与应用

回复 
机器学习
   R&Python机器学习入门 
继续阅读
阅读原文