NBA 历年总冠军数据集处理与各球队冠军数量统计

编辑:  来源:JRSKAN  2024-09-16 15:25:23

本案例要处理的文件为nba.csv,里面记录了历年NBA总冠军的详细信息。文件中的字段从左到右依次为比赛年份、具体日期、冠军、比分、亚军、年度MVP(MVP是Mostnba西部球队,最有价值球员的缩写)。各个字段之间用半角逗号“,”隔开,如图3-1所示。

图3-1 NBA原始文件数据

本课程设计需要对该数据集进行如下处理:

(1)数据清理;

(2)统计各支球队获得的冠军次数;并分别存储东部和西部球队的统计结果。

任务一:实施过程

(1)要求

NBA历史悠久,从1947年到2019年,有些球队已经不复存在(例如芝加哥雄鹿队),有些球队已经更名(例如明尼阿波利斯湖人队现在更名为洛杉矶湖人队)。因此,对于已经不复存在的球队,其名称将继续保存,不做修改;但已经更名的球队需要映射到当前球队名称。

另外,因为需要将球队分为东区和西区,所以应该在球队上加上东区和西区标签。

(2)解题思路

添加球队新旧名字的映射,读取每一行数据时,遇到旧名字时,用新名字替换;

添加东西部分区映射,读取数据时分析冠军球队所在分区,然后添加标识(东部球队用“E”标识,西部球队用“W”标识)

需要注意的是,NBA从1970年开始将联盟划分为东西部,因此需要根据年份进行判断。

(3)核心代码分析

在自定义类中我们首先创建了两个java.util.Map对象分别封装新老球队、东西赛区球队的映射,核心代码如图所示:

图 3-2 封装新旧团队和东西分区的映射对象

映射数据的初始化最好放在类的setup()方法中。该类有四个方法:

无效设置()

void map(KEYIN 键,值,)

空白 ( )

无效运行()

setup()方法一般用来加载一些初始化工作,比如初始化相关数据、建立数据库链接等;run()方法是收尾工作,比如执行map()之后关闭文件或者分配键值等;map()函数描述了对每一行数据的处理逻辑;run()方法定义了上述方法的执行过程,如图3-3所示。通过该方法我们可以看出setup()和run()在对象的生命周期中只会被调用一次,而map()方法只要有新的键和值就会被调用。

图 3-3 类中的 run() 方法

setup()方法中初始化映射数据的核心代码如图3-4所示。

图3-4 映射数据初始化核心代码

最后应该将东西分区的List列表添加到对象中,如图3-5所示。

图 3-5 为对象添加分区

在map方法中,按照上述需求进行逻辑映射,map最终输出的结果为type,Text部分为替换为新名称后的数据,并附加了东区和西区标识,核心代码如图3-6所示。

图3-6 map方法核心代码

main方法中需要定义job启动相关的参数nba西部球队,数据清洗部分其实只需要输出map阶段的结果,不需要进行部分汇总处理,所以不需要配置。不过即使不写类,框架也会添加一个默认的类,即org....,可以使用Job对象的方法,并将其参数设置为0,避免不必要的性能浪费。核心代码如图3-7所示。

图3-7main方法核心代码

任务2:统计各支球队获得的冠军次数,并将统计结果存储在东部赛区、西部赛区、未分赛区三个文件中。

任务 2:解决问题的思路

统计各个球队获得的冠军数量,基本思路和前面程序的逻辑一致,在map阶段解析出冠军球队的名字作为key,用一个值为1的对象作为value,然后传递给,在部分进行加法运算。

另外统计结果需要按照东西分区分别存放在文件中,所以相对比较复杂,从给出清洗后的数据集可以看出应该存放在东分区、西分区、未分区三个文件中,所以需要进行自定义,根据分区标识确定每行数据需要进入哪个分区。

通过job.(3)将指定的数字设置为3。

任务2:核心代码分析

其中map部分主要是解析冠军队名,解析分区标识,并根据分区标识设置键值,value部分则直接取值1,核心代码如图3-9所示。

图3-9 地图核心代码

在定制中需要根据key值确定每行数据进入哪个分区,核心代码如图3-10所示。

图3-10 核心代码

将各部分合并,统计各队获得的冠军数量,核心代码如图3-11所示。

图3-核心代码

在main方法中,除了基本的作业提交所需的参数外,这里还指定了以下内容。由于计算个数的逻辑和 一致,因此直接使用该类。另外还需要指定自定义的类,并将个数设置为3。核心代码如图3-12所示。

图3-12 Main方法核心代码

最终计算结果共有三个文件(不含文件),文件列表如图3-13所示。

图3-13 结果文件列表

三个文件的内容如下:

(1)part-r-00000的内容如图3-14所示。

图 3-14 part-r-00000 的内容

(2)part-r-00001的内容如图3-15所示。

图 3-15 part-r-00001 的内容

(3)part-r-00002的内容如图3-16所示。

图 3-16 part-r-00002 的内容

任务三:统计各队夺冠次数,使用自定义统计实现多文件存储

接下来我们对上面的例子进行修改,通过自定义的方式将东区、西区、无分区的数据分别保存在三个文件中。

(一)解题思路

是框架用于数据输出的抽象父类,该类继承而来,用于定义文件的输出,在stage中默认继承了输出类,我们可以通过继承来实现自己的输出逻辑。

(2)核心代码分析

自定义很简单,在方法中返回一个对象就行,核心代码如图3-17所示。

图3-17 核心代码

我们需要继承来实现自己的输出逻辑。本案例定义了一个类,在其构造方法中,针对不同类型的数据的输出创建了三个对象,在其核心的write方法中,根据分区表述指定了不同分区数据的输出,并在最后的close方法中对三者进行了关闭。核心代码如图3-18所示。

图3-18 核心代码

需要注意的是,在main方法中,既然是自定义的,就不再需要自定义了,另外还需要指定类,核心代码如图3-19所示。

图3-19 Main方法核心代码

最终输出结果与上例基本一致,只是本例代码中直接定义了文件名,最终结果文件列表如图3-20所示。

图3-20 结果文件列表

任务4:仅处理东西分区后的数据

(一)解题思路

前面两个例子,数据是存储在多个文件中的。但是由于本例只要求东、西分区的数据分别存储在不同的文件中,所以将1970年以前的数据分开保存,显得多余。去除这些多余数据非常简单,只需要在例子2、3的map方法中进行过滤即可。不过更好的办法是,使用自定义类,在数据进入map方法之前将其去除。

它是框架中数据读取的抽象父类,被继承,主要用于读取文件,框架默认使用继承,我们可以继承它来实现自己的输出逻辑。

(2)核心代码分析

创建一个类继承,并实现返回自定义对象的方法,核心代码如图3-21所示。

图3-21 核心代码

为了实现定制,需要重写以下方法:

无效(分裂,)

()

()

文本 ()

漂浮 ()

无效关闭()

其中,方法主要用于初始化数据读取所需的一些参数,比如起始位置、终止位置、读取流对象等;该方法在数据读入map方法之前会被调用(参见图3-3),其功能是给键和值赋值;and方法用于获取已经赋值的键和值并传入map方法中;用于计算读取了多少数据;close用于关闭读取流。

在中定义读操作用到的变量,核心代码如图3-22所示。

图3-22 定义读写操作变量

在该方法中对上述变量进行了初始化,核心代码如图3-23所示。

图3-23 方法核心代码

在该方法中,进行了过滤,1970年之前的数据不会传入map方法中nba西部球队,核心代码如图3-24所示。

图3-24 方法核心代码

实现方式及方法,核心代码如图3-25所示。

图3-25及方法核心代码

将上述代码添加到示例2或示例3中,然后在main方法中设置类,核心代码如图3-26所示。

图3-26 Main方法核心代码

运行之后的最终输出中,不会存在分区之前的数据。

  • 上一条:青海站 E 级教练员培训班在贵德开课,促进基层篮球运动发展
  • 下一条:16-17 赛季 NBA 最有价值球员:韦少为何能斩获 MVP?
  • 相关文章