一、业务场景
某大型电商网站收集有用户在2014年购物行为数据,包含了300000条数据记录。现希望大数据分析团队使用Spark技术对这些数据进行分析,以期获得有价值的信息。
二、数据集说明
本案例用到的数据集说明如下:
数据集文件:/data/dataset/batch/user_action.csv
该数据来源于某电商网站的用户在2014年购物行为数据,包含了300000条数据记录。
1. 字段 定义 2. uid (自增序列值) 3. user_id (用户id) 4. item_id (商品id) 5. behaviour_type (包括浏览、购买、退货) 6. item_category (商品分类) 7. visit_data (该记录产生时间) 8. user_address (用户所在地) 9. browser (客户端所使用的浏览器)
三、操作步骤
阶段一、启动HDFS、Spark集群服务和zeppelin服务器
1、启动HDFS集群
在Linux终端窗口下,输入以下命令,启动HDFS集群:
1. $ start-dfs.sh
2、启动Spark集群
在Linux终端窗口下,输入以下命令,启动Spark集群:
1. $ cd /opt/spark 2. $ ./sbin/start-all.sh
3、启动zeppelin服务器
在Linux终端窗口下,输入以下命令,启动zeppelin服务器:
1. $ zeppelin-daemon.sh start
4、验证以上进程是否已启动
在Linux终端窗口下,输入以下命令,查看启动的服务进程:
1. $ jps
如果显示以下6个进程,则说明各项服务启动正常,可以继续下一阶段。
1. 2288 NameNode 2. 2402 DataNode 3. 2603 SecondaryNameNode 4. 2769 Master 5. 2891 Worker 6. 2984 ZeppelinServer
阶段二、准备案例中用到的数据集
1、将本案例要用到的数据集上传到HDFS文件系统的/data/dataset/batch/目录下。在Linux终端窗口下,输入以下命令:
1. $ hdfs dfs -mkdir -p /data/dataset/batch 2. $ hdfs dfs -put /data/dataset/batch/user_action.csv /data/dataset/batch/
2、在Linux终端窗口下,输入以下命令,查看HDFS上是否已经上传了该数据集:
1. $ hdfs dfs -ls /data/dataset/batch/
这时应该看到数据集文件user_action.csv已经上传到了HDFS的/data/dataset/batch/目录下。
阶段三、对数据集进行探索和分析
1、新建一个zeppelin notebook文件,并命名为rdd_project。
2、加载数据集到RDD。在notebook单元格中,输入以下代码,加载数据集到RDD:
1. val filePath = "/data/dataset/batch/user_action.csv" // 定义要加载数据集的hdfs路径 2. val userActionRDD = sc.textFile(filePath) // 读取数据集到rdd 3. 4. userActionRDD.cache // 缓存rdd
同时按下Shift+Enter,执行以上代码。
3、简单探索。
1. userActionRDD.take(1)
同时按下Shift+Enter,执行以上代码,输出内容如下:
Array[String] = Array(1,10001082,285259775,浏览,4076,2014-11-11,福建,Safari)
由以上输出内容可知引数据集的数据格式。其中:
- 数组的第2个元素是用户id
- 数组的第3个元素是商品id
- 数组的第4个元素是用户行为(值包括”浏览”、”购买”、”退货”)
- 数组的第5个元素为该商品所属类别的id
- 数组的第6个元素为此用户行为发生的日期
- 数组的第7个元素为用户用户所在地
- 数组的第8个元素为用户所使用的浏览器类型。
4、转换为RDD[Array[String]]。在notebook单元格中,输入以下代码,对每行数据按逗号进行分割:
1. val userRDD = userActionRDD.map(line => line.split(",")) 2. userRDD.take(2) 3. userRDD.cache
5、查看前10位用户的行为(即behavior_type字段的值)。在notebook单元格中,输入以下代码:
1. userRDD.map(_(3)).take(10).foreach(println)
同时按下Shift+Enter,执行以上代码,输出内容如下:
浏览 浏览 浏览 浏览 浏览 退货 浏览 浏览 浏览 浏览
由以上输出内容可以看出,在前10条用户访问记录中,大多数用户仅仅是浏览商品,甚至还发生了一起退货事件,但是没有购买行为。
6、查看用户访问数据总共有多少。在notebook单元格中,输入以下代码:
1. userRDD.count
同时按下Shift+Enter,执行以上代码,输出内容如下:
Long = 300000
由以上输出内容可以看出,本数据集总共有30万条用户行为的数据记录。
7、在这30万条用户行为记录数据中,包括有多少个用户?在notebook单元格中,输入以下代码:
1. userRDD.map(_(1)).distinct.count
同时按下Shift+Enter,执行以上代码,输出内容如下:
Long = 270
由以上输出内容可以看出,总共有270个用户访问,他们造成了30万条用户行为的数据记录。
8、在这个数据集中,总共包含有多少种商品?在notebook单元格中,输入以下代码:
1. userRDD.map(_(2)).distinct.count
同时按下Shift+Enter,执行以上代码,输出内容如下:
Long = 106919
由以上输出内容可以看出,总共有106919种商品。也就是说,270个用户对十余万种商品进行访问,造成了30万条用户行为的数据记录。
9、这十余万种商品属于多少个商品分类呢?在notebook单元格中,输入以下代码:
1. userRDD.map(_(4)).distinct.count
同时按下Shift+Enter,执行以上代码,输出内容如下:
Long = 3569
由以上输出内容可以看出,数据集中的十余万种商品属于3569个品类。
10、查询2014年12月15号到2014年12月18号有多少人次浏览了商品。在notebook单元格中,输入以下代码:
1. userRDD.filter(_(3)=="浏览"). 2. filter(_(5)>="2014-12-15"). 3. filter(_(5)<"2014-12-18"). 4. count
同时按下Shift+Enter,执行以上代码,输出内容如下:
Long = 25636
由以上输出内容可以看出,在2014年12月15号到2014年12月18号这三天中,一其有25636人次浏览了商品。
11、统计每天网站卖出的商品个数。所谓卖出的商品个数,即用户行为为”购买”的记录数量。在notebook单元格中,输入以下代码:
1. // 这里定义一个转换函数,用来对日期进行格式化 2. def convert(dt:String):String = { 3. val sdf = new java.text.SimpleDateFormat("yyyy-MM-dd") 4. sdf.format(sdf.parse(dt)) 5. } 6. 7. userRDD.filter(_(3)=="购买"). // 仅统计发生了购买的数据 8. map(arr => (convert(arr(5)),1)). // 生成(日期,1)元组 9. reduceByKey(_ + _). // 按天进行统计汇总 10. sortBy(_._1). // 按购买日期进行排序 11. take(5).foreach(println) // 查看前5天的记录
同时按下Shift+Enter,执行以上代码,输出内容如下:
(2014-12-17,326) (2014-12-18,358) (2014-12-16,377) (2014-12-15,462) (2014-12-14,487)
由以上输出内容可以看出,在2014年12月18号这一天,卖出的商品最少;而在2014年12月14号这一天,卖出的商品最多。实际上,卖出商品最少的一天是2014年12月17号这一天,因为这一天没有卖出商品。
12、查询2014年12月14日发货到江西的商品数量。在notebook单元格中,输入以下代码:
1. userRDD.filter(_(3)=="购买").filter(_(5)=="2014-12-14").filter(_(6)=="江西").count
同时按下Shift+Enter,执行以上代码,输出内容如下:
Long = 14
发货到江西的数量,即江西的用户购买的数量。由以上输出内容可以看出,在2014年12月14号这一天,发货到江西的商品有14件。
13、查询用户’100489195’在2014-11-11这一天点击该网站的点击量,以及其点击量在当天网站的总点击量的占比。在notebook单元格中,输入以下代码:
1. // 查询'100489195'用户在2014-11-11这一天点击该网站的点击量 2. userRDD.filter(_(1)=="100489195").filter(_(5)=="2014-11-11").count 3. 4. // 查询在2014-11-11这一天点击该网站的总点击量 5. userRDD.filter(_(5)=="2014-11-11").count
同时按下Shift+Enter,执行以上代码,输出内容如下:
Long = 17 Long = 67150
由以上输出内容可以看出,用户’100489195’在2014-11-11这一天点击该网站的点击量是17次,而当天网站的总点击量是67150。这两个结果相除,就得到了比例结果:17/67150。
14、查询2014-12-18这一天在该网站购买的商品数量超过5个的用户id。在notebook单元格中,输入以下代码:
userRDD.filter(_(3)==“购买”).
filter(_(5)=="2014-12-18").
map(arr => (arr(1),1)).
map(arr => (arr(1),1)).
filter(_._2 > 5).
sortBy(_._2,false).
collect.foreach(println)
同时按下Shift+Enter,执行以上代码,输出内容如下:
(103995979,26) (102115747,26) (102616570,25) (101847145,20) (100695202,12) (101454268,12) (100442521,9) (101490976,9) (102831484,9) (101969992,8) (103193989,8) (103215328,8) (103871479,7) (10176801,7) (103456642,7) (102094417,6) (102033883,6) (101105140,6) (102868558,6) (101982646,6)
由以上输出内容可以看出,2014-12-18这一天在该网站购买的商品数量最多的用户其id是”102115747”。
阶段四、自我练习
请使用Spark RDD,在本案例项目数据集基础上,回答以下问题:
1、统计每天网站卖出的商品个数,按卖出的商品数量由高到低排序输出。
2、请根据用户行为数据,分析用户所采用的浏览器种类,以及每种浏览器所占比例。
3、请根据用户行为数据,分析用户归属地分布。