自定义 UDF 分析 Uber 数据
一、实验介绍
1.1 内容介绍
在本课程中使用 SQL Context 及相关的 API 进行统计分析,最后还将通过一个 Spark 分析旅游数据的实例,进一步学习如何利用 Spark SQL 分析数据。
1.2 实验知识点
- SQL Context
- 自定义 UDF 函数
- SQL 语句
1.3 实验环境
- Ubuntu14.04
- Spark1.6.1
- Xfce终端
1.4 适合人群
本课程难度为一般,属于初级级别课程,适合具有 Spark 基础的用户,熟悉 Spark SQL 的基础知识。
二、数据集介绍
下载 在线 uber 数据,由于需要翻墙,在这里,我已经将数据集整理好上传到实验楼上。Get 数据信息:uber 数据
该数据集共有4
个字段,每个字段的具体含义如下:
字段: 字段类型: 描述信息
dispatching_base_number:String
区域编号
date:String
日期
active_vehicles:Int
使用的机动车数量
trips: Int
旅游次数
三、项目实现
3.1 进入开发环境
进入到实验环境,双击桌面上的 Xfce,效果如下图
请输入以下代码获取数据集。
wget http://labfile.oss.aliyuncs.com/courses/851/uber
请输入以下命令,查看行数
wc -l uber
请输入以下命令,查看前行内容
head -n 10 uber
注意,第一行是各字段的描述信息,即表头并非数据,稍后数据处理时,需要排除掉此行
3.2 启动 spark shell
接下来,我们将使用 spark shell 来编写
请在终端中输入如下代码:
spark-shell
进入到 spark 的 REPL 环境,相当于就是 spark 的 Console。
3.3 导入数据并转换数据
下面我们就进入到实验的关键位置,进行数据的导入,并进行必要的数据格式处理。
3.3.1 导入数据
键入如下命令:
val data= sc.textFile("/home/shiyanlou/uber")
调用 first ()取第一行数据
data.first
可以看到与之前用 linux 命令查到的结果相同,接下来,过滤掉第一行数据。
val hd = data.first()
val datafiltered = data.filter(line => line != hd)
检查行数,显示 354 行,第一行已经过滤掉。
datafiltered.count
3.3.2 转换数据
首先定义一个样例类,封装数据字段。
case class uber(dispatching_base_number:String ,date:String,active_vehicles:Int,trips:Int)
通过 case class 将数据转换为 dataframe
val df = datafiltered.map(x=>x.split(",")).map(x => uber(x(0).toString,x(1),x(2).toInt,x(3).toInt)).toDF
将数据对象存成临时表,便于后续的查询操作
df.registerTempTable("uber")
3.4 自定义 UDF 分析数据
自定义 UDF,解析日期列,UDF 函数其实与 Scala 函数没区别,传几个参数决定几个列,这里我们只传递了一个参数。
def
pas = (s: String) => {
val format = new java.text.SimpleDateFormat("MM/dd/yyyy")
var days =Array("Sun","Mon","Tue","Wed","Thu","Fri","Sat")
val split = days(format.parse(s).getDay).toString
split
}
我们编写的 UDF 采用字符串格式的日期,使用 java 的 SimpleDataFormat 类进行解析,getDay 函数将返回一周的日期数。所以我们创建了一个存储周的名字的数组。根据 getDay 函数的返回值,返回数组的相应索引值。所以最后我们会得到一周中的一天。
最后别忘记将我们编写的 UDF 注册到 Spark SQL 中,register()函数第二个参数是我们自己定义的 UDF 函数,第一个只不过是我们起的别名。
sqlContext.udf.register("ppa",pas)
3.4.1 查询各区域编号的旅游次数
查找每一个 dispatching_base_number(区域编号)在每一天的旅游次数之和,并且按照星期降序排序。
利用自定义的 UDF 解析日期,它返回每天基于日期的行程次数。
val rep = sqlContext.sql("select dispatching_base_number as dis, ppa(date) as dt ,sum(trips) as cnt from uber group by dispatching_base_number,ppa(date) order by cnt desc")
打印结果
rep.collect
所有这些操作,在 spark 的 web 界面都可以看到,双击打开桌面的火狐浏览器,输入 localhost:4040,回车。
可以看到有 4 个 Jobs 已经完成,我的 RDD 操作多一点,不一定与你的相同,继续点击任意一个 jobs(我选择第一个)。
接下来点击 DAG Visualization,可以看到具体的执行计划。
当然通过浏览器看到的更直观,还有很多其他细节就不一一举例了,您可以多了解下,直观的感受下 spark 的强大。
3.4.2 查询各区域编号的机动车的使用
在3.4.1实验基础上可以紧接着查询每一个 dispatching_base_number(区域编号)在每一天的机动车的数量使用情况,并且按照星期降序排序。
利用自定义的 UDF 解析日期,它返回每天基于日期的机动车使用次数。
val rep = sqlContext.sql("select dispatching_base_number as dis, ppa(date) as dt ,sum(active_vehicles) as cnt from uber group by dispatching_base_number,ppa(date) order by cnt desc")
打印结果
rep.collect
3.5 退出 spark-shell 终端
请输入 exit
至此,自定义的 Spark UDF 函数分析 uber 数据的小案例演示就结束了,如果使用可视化工具展示效果会更加直观。
四、总结
本节课主要介绍如何使用 Spark UDF 函数分析 uber 数据,希望帮助您掌握了 SparkSQL 的概念,并学会使用自定义 UDF,因为 spark 的函数有时候并不符合我们的需求。