【版权声明】版权所有,严禁转载,严禁用于商业用途,侵权必究。
作者:厦门大学信息学院人工智能系2021级研究生 夏佳尔
指导老师:厦门大学数据库实验室 林子雨 博士/副教授
相关教材:林子雨、郑海山、赖永炫编著《Spark编程基础(Scala版)》
【查看基于Scala语言的Spark数据分析案例集锦】
本案例针对NBA球员数据进行分析,采用Scala为编程语言,采用Hadoop存储数据,采用Spark对数据进行处理分析,并对结果进行数据可视化。
一、实验环境
1)Linux: Ubuntu18.04.6 LTS
2)Hadoop: 3.1.3
3)Spark:3.2.0
4)Python3.8.10
5)Scala:2.12.15
6)IntelliJ IDEA:2022.1
7)sbt:1.6.2
二、数据处理
(1)数据集说明
本次实验所用数据集来自NBA官网所公布的数据库(https://www.nba.com/stats/), 数据集爬取了自1970年至2015年共计46年的球员比赛数据。可以从百度网盘下载数据集(提取码:ziyu)。数据内容及字段说明如下:
Rk:每个文件中的行号
Player:球员姓名
Pos:球员位置
Age:球员年龄
Tm:所在球队(Team)
G:出场次数(games)
GS:首发次数(games started)
MP:平均每场出场时间(minutes played)
FG:命中次数(field goals)
FGA:投篮出手次数(field goals attempt)
FG%:投篮命中率(field goal percentage)
3P:3分球命中次数(3-pointers)
3PA:3分球出手次数(3-pointer attempt)
3P%:3分球命中率(3-pointer percentage)
2P:2分球命中次数
2PA:2分球出手次数
2P%:2分球命中率
eFG%:有效投篮命中率(不包含罚篮)
FT:罚球(free throw)命中次数
FTA:罚球出手次数
FT%:罚球命中率
ORB:前场篮板(offensive rebound)次数
DRB:后场篮板(deffensive rebound)次数
TRB:篮板总数(total rebound)
AST:助攻次数(assists)
STL:抢断(steal)次数
BLK:盖帽(block)次数
TOV:失误(Turnover)次数
PF:个人犯规(personal foul)次数
PTS:总得分(points)
(2)数据集存储(HDFS)
在获得原始数据之后首先通过Hadoop中的HDFS组件将数据集存放在分布式文件系统HDFS中。具体步骤如下:
①在终端中启动HDFS :/usr/local/hadoop/sbin/start-dfs.sh
②在HDFS中创建存放路径:hdfs dfs -mkdir -p /xje/hadoop/nba
③上传文件至HDFS:hdfs dfs -put basketball /xje/hadoop/nba
注意:本次实验所用数据集是包含了46个csv文件的文件夹,所以直接上传了basketball文件夹,使用单文件数据集时可直接上传csv文件。
(3)数据集预处理
在数据分析之前首先对数据进行预处理,去除数据中的无效数据(如空白行)并对数据进行规范化,使得之后的数据处理能够更加顺利的进行。
具体操作为,直接运行Player_Stats_Preprocess.scala文件,但请确保代码中rawDataPath是正确的数据集路径。
在清理数据集后,由于爬取的数据集是按照年份单独爬取的,所以需要对46个不同年份的数据进行整合处理,直接运行ZscoreCalculator.scala文件,代码会读取每一年的csv文件进行合并,并且对各项数据进行预处理,同时根据球员每年的各项数据计算球员在每一年的zScore,作为对球员表现的评价指标(在实验流程中详细说明),最终整合保存为一个包含每一年数据的文件。
三、配置工程
(1)创建IDEA工程
①首先新建一个工程,点击File -> New -> Project
②基于SBT构建Scala项目,注意选择Scala版本为2.12.15
(2)添加jar包
①打开File -> Projects Structure
②添加Spark jar
(3)配置文件本地单线运行
①在右上角选择Edit Configuration
②在Modify option中选择 AddVM options
③在VM option中输入-Dspark.master=local指示本程序本地单线程运行
四、数据分析
(1)筛选1970到2015赛季间主要数据排行前100名
使用spark.sql语句从数据库中select出球员姓名、年份、所在队伍以及待分析的数据(包括得分、篮板、助攻、盖帽、抢断),同时通过GP也就是出场数进行筛选,必须满足出场数大于30,防止统计到低出场数的不可靠数据。
按照得分或篮板等数据进行降序排序后进行输出,并写入csv中存储至HDFS。
(2)分析自1970至2015赛季以来每年的三分球数据变化
该部分分析随着赛季发展,三分球在比赛中的占比变化,主要分析三分球的出手数、命中数和命中率。分析前首先声明一个三分球类来接受所需的三分球相关的字段数据,然后分析的具体流程如下:
①读取csv数据集并通过出场数进行数据过滤
②选择所需的字段并创建Dataset
③按年进行分组并聚合每一年的三分数据
④保存处理完的数据
具体代码如下:
(3)所有球员服役队伍数量情况统计
该部分分析不同球员在联盟中更换队伍的情况,即对每个球员所在队伍的种类数量进行统计,具体流程如下:
①读取csv数据集
②选出name和team字段创建Dataset类
③按照不同球员的名字进行分组,对每一球员队伍出现的种类数量进行统计
④对于统计后的每个球员的队伍数再次进行聚合统计
⑤保存处理完的数据
具体代码如下:
主要使用Dataset类的GroupBy和agg操作对数据进行分组和聚类,最终统计出总的队伍变更数量,输出时按照队伍的数量进行排序,运行后的输出结果如下图:
(4)分析年龄和球龄与球员价值之间的关系
该部分分析球员的价值与年龄和球龄之间关系,首先需要对球员价值有一个量化的评估,这部分是已经在数据预处理中提到的zScore的计算, zScore是结合三分球命中数、篮板总数、助攻总数、抢断总数、盖帽总数、失误总数、得分总数共计七个指标进行评估,nzScore是在此基础之上增加投篮命中率、罚球命中率两个指标共计九个指标进行评估。计算代码如下:
所有的各项指标会与当年所有数据计算出的平均数和标准方差进行标准化,保证每个数据在同一尺度并确保每一年的评价指标相对齐,在获得每个球员每一年的评价得分之后,随着年份变化对球员的价值变化进行评估并聚合,得到随着年龄或是球龄变化时球员价值的变化关系。具体代码如下:
(5)特定球员的数据及价值变化分析
这部分分析任意一名球员在不同赛季的数据变化,再根据已经计算出的球员价值zScore同步分析球员的数据随着赛季不断发展中发生的变化。同样先利用spark读入已经预处理好的csv文件,再通过sql的select方法从指定球员的数据中筛选出所需要的字段,具体代码如下:
五、结果可视化
(1)可视化工具
对结果数据的可视化使用python语言,具体所用的版本及库如下:
Python 3.10.4
Pandas
Matplotlib