美文网首页
小数据小分析——谁是本赛季最佳后卫?

小数据小分析——谁是本赛季最佳后卫?

作者: 张伟松 | 来源:发表于2017-07-09 23:04 被阅读64次

学习数据分析一月有余,终于鼓起勇气开启了自己的实战演练。本次练习的文件从BasketballReference 上下载,2016~16赛季球员数据,自定义了几个分析任务,通过R对数据框、字符、数字的操作,熟悉和掌握数据分析的基本方法。

本篇原本是在知乎上操作的。熬夜到2点写的文章因为知乎平台一个未知错误,导致图片代码全部消失,这里我只想说¥%(&%…,于是果断放弃知乎

数据分析的一遍流程是:

业务理解=>数据准备/预处理=>分析/挖掘=>评估=>应用/部署/报告/决策

获取数据

表格的主要字段有球员姓名,位置,出场次数,首发次数等,如下图。

2016~16赛季球员数据

明确目标

分析任务是:

  1. 算出得分最多的前十名
  2. 各个位置(PG,SG,SF,PF,C)的最佳球员
  3. 算出每个球队在16~17赛季的总得分
  4. 绘制年龄和命中率的趋势图
  5. 答案在最后

数据预处理

首先在windows下读取excel文件,这里有一些坑:

  • 需要用到的包是openxlsx,但是有时会安装失败,这时就需要先安装Rtools
    然后在R中运行
Sys.setenv("R_ZIPCMD" = "C:/Rtools/bin/zip.exe")
  • library导入所需的包之后,openxlsx中的函数read.xlsx()可以很方便的读取文件,函数中的文件路径,可以是相对路径,亦可以是绝对路径。如果使用相对路径,相对的是当前的工作目录getwd()可查看。后来发现可以使用file.choose()来直接拉取windows的文件浏览器。
nbaData <- read.xlsx(file.choose())

下载的原始数据感觉不是美美哒,需要进行数据预处理,预处理的主要工作包含重命名列,处理缺失值,处理日期,数值转换,排序

  1. 处理缺失值
    函数na.omit()用来删除数据框中含有缺失值的记录
    nbaData <- na.omit(nbaData)
  2. 在原始数据中,姓名带斜杠,后面有一些标志:

好像是每个球员的某种唯一编码,不太懂。去掉好处理。

library(stringr)
fixednames <- str_split_fixed(nbaData$Player,'\\\\',n=2)[,1]
nbaData$Player <- fixednames

斜杠\是R中的转义字符,使用\\\\\\\\才能正确表达使用斜杠截取的含义,str_split_fixed是stringr中的函数,看名字就能才出来它是str_split的加强版,返回的是含有n个元素的矩阵。

  • 这里遇到一个问题,某些球员如 Quincy Acy 先后在三个球队服役,这里为了方便处理,只保留第一个
nbaData <- nbaData[!duplicated(nbaData[,c("Player")]),]

计算关键指标

算出得分最多的前十名

各个位置(PG,SG,SF,PF,C)的最佳球员

每个位置的评判 标准不一样,比如控后PG就更看重助攻AST而不是篮板TRB,而中锋C的核心指标应该是篮板和盖帽BLK。况且每个字段的值域还都不一样,这就比较蛋疼了。我想到一个办法——标准化。

这里我们做一些简单的规定,对于每个位置,篮板数TRB、助攻AST、盖帽BLK、场均得分PS/G、失误PF,各自权重如下:

weightPG  <- c(0,4,0,3,-1)
weightSG <- c(0,2,1,4,-2)
weightSF <- c(2,1,2,4,-1)
weightPF <- c(3,1,3,3,-1)
weightC <- c(4,2,4,3,-1)

可能不是很合理,凑合用吧先
发现严重问题
并不是每个人的位置都是固定的,比如杰弗瑞·洛文吉这货,就既是中锋,又是大前。我想知道还有那些人担任着多种角色,进行了如下尝试:
首先定义全部的位置
allpos <- c('PG','SG','SF','PF','C')
然后查看在所有球员中,哪些人的位置在这个向量里面is.element(nbaData$Pos,allpos)
返回的是一堆逻辑向量,在总表中
nbaData[!is.element(nbaData$Pos,allpos),]
输出的结果如下

   Rk            Player  Pos Age  Tm  G GS MP  FG FGA  FG%  3P 3PA   3P%
310 254 Joffrey Lauvergne PF-C  25 TOT 70  1 14 2.1 4.8 0.44 0.5 1.4 0.337
     2P 2PA   2P% eFG%  FT FTA  FT% ORB DRB TRB AST STL BLK TOV  
310 1.6 3.4 0.483 0.49 0.7   1 0.63   1 2.6 3.6   1 0.4 0.1 0.8 1.2  5.4
    score
310   378

就只有你一个。好吧去掉。
nbaData <- nbaData[is.element(nbaData$Pos,allpos),]
把所有的球员按位置分组

PG <- nbaData[nbaData$Pos=='PG',]
SG <- nbaData[nbaData$Pos=='SG',]
SF <- nbaData[nbaData$Pos=='SF',]
PF <- nbaData[nbaData$Pos=='PF',]
C <- nbaData[nbaData$Pos=='C',]

然后用函数scale算出他们篮板数TRB、助攻AST、盖帽BLK、场均得分PS/G、失误PF的标准差,与权重相乘,求和,是他们的最终得分。
基于每个位置的方法大同小异,我以控球后卫PG为例。

valueName <-c('TRB','AST','BLK','PS/G','PF')
sd <- t(t(scale(PG[valueName ]))*weightPG)
PG$est<-  round(apply(sd,1,sum),digits=2)
PG <- PG[order(PG$est,decreasing = T),]
firstPG <- PG[1,]

好吧,这样算下来还是威斯布鲁克。
按这个步骤算出其他位置:

firstSG <- 'DeMar DeRozan'
firstSF <- 'Kevin Durant'
firstPF <- 'Kristaps Porzingis'
firstC <- 'Anthony Davis'

除了杜兰特,其他人是谁?

算出每个球队在16~17赛季的总得分

数据表中只有每个球员的得分,和所在球队,我要做的就是根据球队,计算球员的总得分,我想到了可以用SQL中的SELECT sum(score) FROM nbaData GROUP BY Tm的方法,不过既然要学习R,就要用R的方法,找了一早上,发现了tapply这个函数可以进行分组计算。

teamscore <- tapply(nbaData$score, nbaData$Tm, sum)

然后进行绘图

  • paste函数默认以空格分隔,设置sep=""可以避免空格
  • text函数用来为plot图表添加坐标上的数值。
  • X轴上的名字总是显示不全,谁能教教我?
filename <- paste('score of each team','.png',sep="")
png(file=filename)
barplot(height=teamscore,names.arg=teams,xlab="team",ylab="score",col="blue",
        main="score of each team",border="red") 
text(x,teamscore,labels=teamscore,cex=.7,pos=1,col='orange')
dev.off()
score of each team.png

很丑我知道。

绘制年龄和命中率的趋势图

计算命中率,图表中有2P%(2分球命中率)、3P%(3分球命中率),和FT%(罚篮命中率),罚球不参与讨论。2P%和3P%打算取平局值,能说明问题就行。
nbaData$AvePR <- apply(nbaData[c('2P%','3P%')],1,mean)
首次是求出了平均值,然后绘制散点图,并根据散点图拟合出回归线。起初使用attach和detach会报错The following objects are masked _by_.GlobalEnv:查了一下原来是因为attach出来的变量有重名的,并推荐使用with。


with(nbaData,{ 
  filename <- paste('各年龄球员命中率','.png',sep="")
  png(file=filename)
  plot(Age,AvePR,pch=16,xlab="年龄",ylab="命中率",col="blue",
       main="各年龄球员命中率")
  abline(lm(AvePR~Age)) 
  dev.off() 
}) 

猜一下那个年龄最大的球员是谁。

各年龄球员命中率.png
有点意外,命中率竟然和年龄没多大关系

nbaData[nbaData$Age == max(nbaData$Age),]

40岁的卡特

答案

  1. 算出得分最多的前十名
    他们是威斯布鲁克、 哈登、小托马斯 、安东尼·戴维斯、22岁的卡尔·安东尼·唐斯、利拉德 、德玛尔·德罗赞、库里、我詹 、德马库斯·考辛斯,不服来辩。

  2. 各个位置(PG,SG,SF,PF,C)的最佳球员
    控后:威斯布鲁克
    分后: 德玛尔·德罗赞
    小前: 杜兰特
    大前:克里斯塔普斯·波尔津吉斯
    中锋: 安东尼·戴维斯

  3. 算出每个球队在16~17赛季的总得分
    参看上面的图。

  4. 绘制年龄和命中率的趋势图
    参看上一题。

总结

6月27号开始本次本次实践,中间断断续续发生一些事情,本不该影响到学习的,到做完已经花费10多天,是不是有点慢了?恩姆。好歹自己坚持下来做完了,小小一张表竟然蕴含了这么多信息,简直太有意思,体会到所谓冰山一角的含义了。所以,慢就是快

相关文章

网友评论

      本文标题:小数据小分析——谁是本赛季最佳后卫?

      本文链接:https://www.haomeiwen.com/subject/ffrrhxtx.html