本实验所用数据为国内某超市从2012年8月1日到2013年8月1日共一年的交易数据,包含了812,847条交易、2,893,385件单个商品以及20,154名顾客。
该数据包含了3个数据集。
- 交易概况
数据集已经存放在HDFS上,路径为“/data/13/2/sales_head/sales_head.csv”,各字段以制表符分隔。数据集还存放在了Hive上,表名为“bigdata_cases.retail_sales_head”。
各字段的定义为:
字段 定义
BillId 交易标识符
CustId 顾客会员标识符,非会员则为空
Quantity 交易包含的商品种类数
TransTime 交易时间
OrigTotalPrice 交易原始总价,可能包含分
Pay 顾客支付金额
Change 找零
ActualTotalPrice 交易实际总价,只精确到角
数据集的前5行为:
student1@master:~$ hdfs dfs -cat /data/13/2/sales_head/sales_head.csv | head -5
00034121002436593 600120168 3 2012-08-01 07:46:10 8.84 10 1.2 8.8
00034121002436594 1 2012-08-01 07:46:53 19.59 20 0.5 19.5
00034121002436595 2 2012-08-01 07:47:35 7 7 7
00034121002436596 600120168 3 2012-08-01 07:48:30 28.01 103 75 28
00034121002436597 600799218 2 2012-08-01 07:49:32 19.9 20 0.1 19.9
- 交易明细
数据集已经存放在HDFS上,路径为“/data/13/2/sales_detail/sales_detail.csv”,各字段以制表符分隔。数据集还存放在了Hive上,表名为“bigdata_cases.retail_sales_detail”。
各字段的定义为:
字段 定义
BillId 交易标识符
RowNo 商品在交易中的次序
TransTime 交易时间
GoodId 商品标识符
Barcode 商品条形码
GoodName 商品名称
Unit 单位
Quantity 商品数量
OrigUnitPrice 商品原始单价
OrigTotalPrice 商品原始总价
ActualUnitPrice 商品实际单价
ActualTotalPrice 商品实际总价
数据集的前5行为:
student1@master:~$ hdfs dfs -cat /data/13/2/sales_detail/sales_detail.csv | head -5
00034121002436593 1 2012-08-01 07:45:38 5440483 2186463 苦瓜(一级) 公斤 0.262 4 1.048 3.6 0.94
00034121002436593 2 2012-08-01 07:45:39 5440483 2186463 苦瓜(一级) 公斤 0.192 4 0.768 3.6 0.69
00034121002436593 3 2012-08-01 07:45:45 5440466 2186359 南瓜(一级) 公斤 4.052 1.98 8.023 1.78 7.21
00034121002436594 1 2012-08-01 07:45:26 5110324 6934665081392 蒙牛益生菌酸牛奶(原味)1.2kg 桶 1 19.59 19.59 19.59 19.59
00034121002436595 1 2012-08-01 07:47:18 5110467 6901209206146 光明酸牛奶(红枣味)180g 盒 2 3.5 7 3.5 7
- 商品信息
数据集已经存放在HDFS上,路径为“/data/13/2/good/good.csv”,各字段以制表符分隔。数据集还存放在了Hive上,表名为“bigdata_cases.retail_good”。
各字段的定义为:
字段 定义
GoodId 商品标识符
Category1Name 商品所属的大类名称
Category2Name 商品所属的中类名称
Category3Name 商品所属的小类名称
Category4Name 商品所属的细类名称
BrandName 顾客支付金额
GoodName 商品名称
数据集的前5行为:
student1@master:~$ hdfs dfs -cat /data/13/2/good/good.csv | head -5
1010226 烟酒纯鲜奶 烟 香烟 进口烟 爱喜 爱喜薄荷香烟20支
1010281 烟酒纯鲜奶 烟 香烟 进口烟 万宝路 万宝路(软红)
1010280 烟酒纯鲜奶 烟 香烟 进口烟 万宝路 万宝路(硬白)
1010151 烟酒纯鲜奶 烟 香烟 杭产烟 阳光利群 利群(阳光)
1010400 烟酒纯鲜奶 烟 香烟 杭产烟 利群 利群(软老板)
[实验步骤提示]
在以下提示步骤中,步骤1是用Hive做数据分析和数据准备,所有代码在大数据计算集群上执行,步骤2是用R语言做数据可视化。
- 用Hive做数据分析和数据准备
a. 统计周末和工作日每小时的销售额和交易数量
统计周末和工作日每小时的销售额和交易数量,其中2012年8月4日是周日,2012年8月6日是周一。
hive -e \
"select substr(TransTime, 1, 10) as Date, hour(TransTime) as Hour, sum(ActualTotalPrice) as Revenue, count(1) as Transaction
from bigdata_cases.retail_sales_head
where TransTime like '2012-08-04%' or TransTime like '2012-08-06%'
group by substr(TransTime, 1, 10), hour(TransTime);" \
1.csv
得到结果的前10行:
Date Hour Revenue Transaction
2012-08-04 7 1585.4000000000003 58
2012-08-04 8 15329.099999999984 395
2012-08-04 9 12841.179999999991 329
2012-08-04 10 10570.569999999996 225
2012-08-04 11 3532.960000000001 112
2012-08-04 12 3795.7900000000004 76
2012-08-04 13 3080.2999999999993 57
2012-08-04 14 6073.070000000002 116
2012-08-04 15 7045.820000000001 167
2012-08-04 16 8614.669999999995 207
b. 统计一年内每天的销售额和交易数量
统计一年内每天的销售额和交易数量,为之后做数据可视化做准备。
hive -e \
"select substr(TransTime, 1, 10) as Date,
sum(ActualTotalPrice) as Revenue, count(1) as Transaction
from bigdata_cases.retail_sales_head
group by substr(TransTime, 1, 10);" \
2.csv
得到结果的前10行:
Date Revenue Transaction
2012-08-01 112761.48999999973 2542
2012-08-02 93819.77000000012 2250
2012-08-03 118865.15999999989 2570
2012-08-04 121632.47999999982 2715
2012-08-05 119397.88999999996 2678
2012-08-06 109638.58999999944 2358
2012-08-07 96941.17999999986 2331
2012-08-08 12885.159999999996 333
2012-08-09 111507.0099999997 2379
2012-08-10 127085.07999999999 2539
c. 统计一年内每天各类商品的销售额和交易数量
统计一年内每天各类商品的销售额和交易数量。
hive -e \
"select substr(a.TransTime, 1, 10) as Date, b.Category1Name as Category,
sum(ActualTotalPrice) as Revenue, count(1) as Transaction
from bigdata_cases.retail_sales_detail a
inner join bigdata_cases.retail_good b on a.GoodId=b.GoodId
where b.Category1Name <> '#N/A'
group by substr(a.TransTime, 1, 10), b.Category1Name;" \
3.csv
得到结果的前10行:
Date Category Revenue Transaction
2012-08-02 干货 16929.53999999998 1070
2012-08-02 文玩 1906.6899999999998 86
2012-08-02 蔬菜 20.27 3
2012-08-03 烟酒 8616.389999999994 591
2012-08-03 粮油 20934.70000000007 1008
2012-08-03 纸品 5170.299999999996 469
2012-08-03 鞋子 1116.11 40
2012-08-03 饼干 10314.989999999967 1812
2012-08-04 家电 1846.2400000000002 33
2012-08-04 服装 2480.0600000000018 65
d. 统计所有用户的最近消费间隔、消费频次和消费金额
统计所有用户的最近消费间隔、消费频次和消费金额。
hive -e \
"select CustId, min(round((unix_timestamp('2013-08-01 00:00:00') - unix_timestamp(TransTime)) / 3600 / 24)) as Recency,
count(1) as Frequency, sum(coalesce(ActualTotalPrice,0)) as Monetary
from bigdata_cases.retail_sales_head
where CustId is not null
group by CustId;" \
4.csv
得到结果的前10行:
CustId Recency Frequency Monetary
600000309 42.0 11 232.40000000000003
600000430 344.0 1 11.7
600000951 146.0 2 0.0
600000981 4.0 9 204.49
600000984 7.0 31 1159.7600000000002
600005706 218.0 1 29.3
600008753 100.0 44 1238.8000000000002
600008756 59.0 13 1140.68
600008757 0.0 248 18182.710000000006
600008758 34.0 74 4434.0
- 用R语言做数据可视化
a. 载入相关程序包
载入相关程序包。将Hive输出的结果文件复制到R语言可访问的路径如“D:\workspace\”。
> library(ggplot2)
> library(dplyr)
Attaching package: 'dplyr'
The following objects are masked from 'package:stats':
filter, lag
The following objects are masked from 'package:base':
intersect, setdiff, setequal, union
b. 画出周末和工作日每小时的交易数量
画出周末和工作日每小时交易数量的平滑曲线,其中横坐标表示小时,纵坐标表示交易数量,灰色区域表示交易数量的95%置信区间。
> data1 <- read.table("D:/workspace/1.csv", sep = "\t", stringsAsFactors = FALSE)
> names(data1) <- c("Date", "Hour", "Revenue", "Transaction")
> ggplot(data1, aes(x = Hour, y = Transaction, group = Date)) + geom_smooth(aes(colour = Date),
+ size = 2)
geom_smooth: method="auto" and size of largest group is <1000, so using loess. Use 'method = x' to change the smoothing method.
c. 画出一年内每天的交易数量
画出一年内每天交易数量的平滑曲线,其中横坐标表示日期,纵坐标表示交易数量,灰色区域表示交易数量的95%置信区间。
> data2 <- read.table("D:/workspace/2.csv", sep = "\t", stringsAsFactors = FALSE)
> names(data2) <- c("Date", "Revenue", "Transaction")
> data2$Date <- as.POSIXct(data2$Date)
> ggplot(data2, aes(x = Date, y = Transaction)) + geom_smooth(colour = "red",
+ size = 2)
geom_smooth: method="auto" and size of largest group is <1000, so using loess. Use 'method = x' to change the smoothing method.
d. 画出一年内每天各类商品的交易数量
画出粮油、干货、烟酒、日化和饼干在一年内每天交易数量的平滑曲线,其中横坐标表示日期,纵坐标表示交易数量,灰色区域表示交易数量的95%置信区间。
> data3 <- read.table("D:/workspace/3.csv", sep = "\t", fileEncoding = "UTF-8")
> names(data3) <- c("Date", "Category", "Revenue", "Transaction")
> data3$Date <- as.POSIXct(data3$Date)
> data3 <- filter(data3, Category == "粮油" | Category == "干货" | Category ==
+ "烟酒" | Category == "日化" | Category == "饼干")
> ggplot(data3, aes(x = Date, y = Transaction, group = Category)) + geom_smooth(aes(colour = Category),
+ size = 1)
geom_smooth: method="auto" and size of largest group is <1000, so using loess. Use 'method = x' to change the smoothing method.
e. 将所有顾客用RFM模型聚成3类
将所有顾客按最近消费间隔(recency)、消费频次(frequency)和消费金额(monetary)用Kmeans算法聚成3类。在聚类前需要对3个字段分别取对数并归一化。
> data4 <- read.table("D:/workspace/4.csv", sep = "\t", stringsAsFactors = FALSE)
> names(data4) <- c("CustId", "Recency", "Frequency", "Monetary")
> data4 <- filter(data4, Recency >= 0 & Frequency <= 150 & Monetary <= 10000)
> data4$CustId <- as.character(data4$CustId)
> data4.scale <- scale(log1p(data4[, -1]))
> clust <- kmeans(data4.scale, 3)
> expm1(t(t(clust$centers) * attr(data4.scale, "scaled:scale") + attr(data4.scale,
+ "scaled:center")))
Recency Frequency Monetary
1 196.915198 2.293729 76.29807
2 121.647601 12.065080 657.18697
3 4.366358 28.047474 1485.28480
画出每个顾客的类别和类别的中心(用空心圆圈表示)。
> plot(rbind(as.data.frame(expm1(t(t(data4.scale) * attr(data4.scale, "scaled:scale") +
+ attr(data4.scale, "scaled:center")))), expm1(t(t(clust$centers) * attr(data4.scale,
+ "scaled:scale") + attr(data4.scale, "scaled:center")))), col = c(clust$cluster,
+ 1:3), pch = c(rep(1, dim(data4)[1]), rep(10, 3)), cex = c(rep(0.1, dim(data4)[1]),
+ rep(3, 3)))