原创/朱季谦

本文适合入门Spark RDD的计算处理。

在日常工作当中,经常遇到基于Spark去读取存储在HDFS中的批量文件数据进行统计分析的案例,这些文件一般以csv或者txt文件格式存在。例如,存在这样一份消费者行为数据,字段包括消费者姓名,年龄,性别,月薪,消费偏好,消费领域,购物平台,支付方式,单次购买商品数量,优惠券获取情况,购物动机。

基于这份消费者行为数据,往往会有以下一些分析目标:

  • 用户统计学分析:针对性别、年龄等属性进行统计分析,了解消费者群体的组成和特征。
  • 收入与购买行为的关系分析:通过比较月薪和单次购买商品数量之间的关系,探索收入水平对消费行为的影响。
  • 消费偏好和消费领域的分析:查看不同消费者的消费偏好(例如性价比、功能性、时尚潮流等)和消费领域(例如家居用品、汽车配件、美妆护肤等),以了解他们的兴趣和偏好。
  • 购物平台和支付方式的分析:研究购物平台(例如天猫、淘宝、拼多多等)和支付方式(例如微信支付、支付宝等)的选择情况,了解消费者在电商平台上的偏好。
  • 优惠券获取情况和购物动机的关系:观察优惠券获取情况和购物动机之间的联系,探索消费者是否更倾向于使用优惠券进行购物。

针对这些需求,就可以使用Spark来读取文件后,进一步分析处理统计。

接下来,就是针对以上分析目标,设计一番Spark代码计算逻辑,由此可入门学习下Spark RDD常用用法。

获取一份具备以下字段的csv随机假样本,总共5246条数据,包括“消费者姓名,年龄,性别,月薪,消费偏好,消费领域,购物平台,支付方式,单次购买商品数量,优惠券获取情况,购物动机”。

Amy Harris,39,男,18561,性价比,家居用品,天猫,微信支付,10,折扣优惠,品牌忠诚
Lori Willis,33,女,14071,功能性,家居用品,苏宁易购,货到付款,1,折扣优惠,日常使用
Jim Williams,61,男,14145,时尚潮流,汽车配件,淘宝,微信支付,3,免费赠品,礼物赠送
Anthony Perez,19,女,11587,时尚潮流,珠宝首饰,拼多多,支付宝,5,免费赠品,商品推荐
......

将样本存放到项目目录为src/main/resources/consumerdata.csv,然后新建一个Scala的object类,创建一个main方法, 模拟从HDSF读取数据,然后通过.map(_.split(","))将csv文件每一行切割成一个数组形式的RDD

  def main(args: Array[String]): Unit = {
val conf = new SparkConf().setMaster("local").setAppName("consumer")
val ss = SparkSession.builder().config(conf).getOrCreate()
val filePath: String = "src/main/resources/consumerdata.csv"
val consumerRDD = ss.sparkContext.textFile(filePath).map(_.split(","))

可以写一段代码打印看一下consumerRDD结构——

    consumerRDD.foreach(x => {
x.foreach(y => print(y +" "))
println()
})

打印结果如下——

这个RDD相当于把每一行当作里一个Array[]数组,第一行的Array0是消费者姓名,即Amy Harris,Array1是年龄,即39,以此类推。

消费者姓名 年龄 性别 月薪 消费偏好 消费领域 购物平台 支付方式 单次购买商品数量 优惠券获取情况 购物动机
Amy Harris 39 18561 性价比 家居用品 天猫 微信支付 10 折扣优惠 品牌忠诚
Lori Willis 33 14071 功能性 家居用品 苏宁易购 货到付款 1 折扣优惠 日常使用
。。。

获取到该RDD后,就可以进行下一步的统计分析了。

一、统计消费者支付方式偏好分布

这行代码意思,x.apply(7)表示取每一行的第八个字段,相当数组Array[7],第八个字段是【支付方式】。

  • map(x=>(x.apply(7),1))表示是对RDD里每一行出现过的支付方式字段设置为1个,例如,第一行把原本数组格式Array的RDD做了转换,生成(微信支付,1)格式的新RDD,表示用微信支付的用户出现了1次。
  • reduceByKey(_ + _)表示按RDD的key进行聚合统计,表示统计微信支付出现的次数,支付宝出现的次数等。最后,通过
  • sortBy(_._2,false)表示按照key-value当中的value进行倒序排序,false表示倒叙,true表示升序。

因此就可以按照以上格式,对文本数据里的每一个字段做相应分析,后文其他计算逻辑也是类似。

consumerRDD.map(x => (x.apply(7),1)).reduceByKey(_ + _).sortBy(_._2, false).foreach(println)

打印结果如下:

二、统计购物平台偏好分布

x.apply(5)表示取每一行的第六个字段,相当数组Array[5],第六个字段是【购物平台】。

同前文的【统计消费者支付方式偏好分布】一样,通过map(x=>(x.apply(5),1))生成(购物平台,1)格式的RDD,然后再通过reduceByKey算子针对相同的key做统计,最后倒序排序。

consumerRDD.map(x => (x.apply(5), 1)).reduceByKey(_ + _).sortBy(_._2, false).foreach(println)

打印结果——

三、统计购物偏好方式分布

x.apply(4)表示取每一行的第五个字段,相当数组Array[4],第五个字段是【消费领域】。

consumerRDD.map(x => (x.apply(4), 1)).reduceByKey(_ + _).sortBy(_._2, false).foreach(println)

打印结果:

四、统计购物动机分布

x.apply(10)表示取每一行的第十个字段,相当数组Array[10],第10个字段是【购物动机】。

consumerRDD.map(x => (x.apply(10), 1)).reduceByKey(_ + _).sortBy(_._2, false).foreach(println)

打印结果——

五、消费者年龄分布

该需求通过将RDD映射成DataFrame数据集,方便用SQL语法处理,按照年龄区间分区,分别为"0-20","21-30","31-40"

......这个分区字符串名,就相当key,value表示落在该分区的用户数量。这时,就可以分组做聚合统计了,统计出各个年龄段的消费者数量。

//取出consumerRDD每一行数组需要的字段
val rowRDD = consumerRDD.map{
x => Row(x.apply(0),x.apply(1).toInt,x.apply(2),x.apply(3).toInt,x.apply(4),x.apply(5),x.apply(6),x.apply(7),x.apply(8).toInt,x.apply(9),x.apply(10))
} //设置字段映射
val schema = StructType(Seq(
StructField("consumerName", StringType),
StructField("age", IntegerType),
StructField("gender", StringType),
StructField("monthlyIncome", IntegerType),
StructField("consumptionPreference", StringType),
StructField("consumptionArea", StringType),
StructField("shoppingPlatform", StringType),
StructField("paymentMethod", StringType),
StructField("quantityOfItemsPurchased", IntegerType),
StructField("couponAcquisitionStatus", StringType),
StructField("shoppingMotivation", StringType) ))
val df = ss.createDataFrame(rowRDD, schema).toDF()
//按年龄分布计算
val agedf = df.withColumn("age_range",
when(col("age").between(0, 20), "0-20")
.when(col("age").between(21, 30), "21-30")
.when(col("age").between(31, 40), "31-40")
.when(col("age").between(41, 50), "41-50")
.when(col("age").between(51, 60), "51-60")
.when(col("age").between(61, 70), "61-70")
.when(col("age").between(81, 90), "81-90")
.when(col("age").between(91, 100), "91-100")
.otherwise("Unknow")
)
//分组统计
val result = agedf.groupBy("age_range").agg(count("consumerName").alias("Count")).sort(desc("Count"))
result.show()

打印结果:

六、统计年龄分布

类似年龄分布的操作。

val sexResult = agedf.groupBy("gender").agg(count("consumerName").alias("Count")).sort(desc("Count"))
sexResult.show()

打印结果:

除了以上的统计分析案例之外,还有优惠券获取情况和购物动机的关系、消费领域方式等统计,可以进一步拓展分析。

本文基于分析消费者行为数据,可以入门学习到,Spark如何读取样本文件,通过map(_.split(","))处理样本成一个数组格式的RDD,基于该RDD,可以进一步通过map、reduceByKey、groupBy等算子做处理与统计,最后获取该样本的信息价值。

基于Spark对消费者行为数据进行数据分析开发案例的更多相关文章

  1. 大数据实时处理-基于Spark的大数据实时处理及应用技术培训

    随着互联网.移动互联网和物联网的发展,我们已经切实地迎来了一个大数据 的时代.大数据是指无法在一定时间内用常规软件工具对其内容进行抓取.管理和处理的数据集合,对大数据的分析已经成为一个非常重要且紧迫的 ...

  2. 基于FPGA的光口通信开发案例|基于Kintex-7 FPGA SFP+光口的10G UDP网络通信开发案例

    前言 自著名华人物理学家高锟先生提出"光传输理论",实用化的光纤传输产品始于1976年,经历了PDH→SDH→DWDM→ASON→MSTP的发展历程.本世纪初期,ASON/OADM ...

  3. 数据分析师的福音——VS 2017带来一体化的数据分析开发环境

    (此文章同时发表在本人微信公众号“dotNET开发经验谈”,欢迎右边二维码来关注.) 题记:在上个月的Connect() 2016大会上,微软宣布了VS 2017 RC的发布,其中为数据分析师带来了一 ...

  4. 苏宁基于Spark Streaming的实时日志分析系统实践 Spark Streaming 在数据平台日志解析功能的应用

    https://mp.weixin.qq.com/s/KPTM02-ICt72_7ZdRZIHBA 苏宁基于Spark Streaming的实时日志分析系统实践 原创: AI+落地实践 AI前线 20 ...

  5. 徒手打造基于Spark的数据工厂(Data Factory):从设计到实现

    在大数据处理和人工智能时代,数据工厂(Data Factory)无疑是一个非常重要的大数据处理平台.市面上也有成熟的相关产品,比如Azure Data Factory,不仅功能强大,而且依托微软的云计 ...

  6. 客户流失?来看看大厂如何基于spark+机器学习构建千万数据规模上的用户留存模型 ⛵

    作者:韩信子@ShowMeAI 大数据技术 ◉ 技能提升系列:https://www.showmeai.tech/tutorials/84 行业名企应用系列:https://www.showmeai. ...

  7. 【基于spark IM 的二次开发笔记】第一天 各种配置

    [基于spark IM 的二次开发笔记]第一天 各种配置 http://juforg.iteye.com/blog/1870487 http://www.igniterealtime.org/down ...

  8. Spark:大数据的电花火石!

    什么是Spark?可能你很多年前就使用过Spark,反正当年我四六级单词都是用的星火系列,没错,星火系列的洋名就是Spark. 当然这里说的Spark指的是Apache Spark,Apache Sp ...

  9. 京东基于Spark的风控系统架构实践和技术细节

    京东基于Spark的风控系统架构实践和技术细节 时间 2016-06-02 09:36:32  炼数成金 原文  http://www.dataguru.cn/article-9419-1.html ...

  10. 使用Spark加载数据到SQL Server列存储表

    原文地址https://devblogs.microsoft.com/azure-sql/partitioning-on-spark-fast-loading-clustered-columnstor ...

随机推荐

  1. Linux 修改文本dos/unix 格式

    使用 vi 命令打开文件,使用 :set ff 查看格式 如果显示dos,可使用 :set ff=unix 修改 pem 证书,使用 cat xx.key xx.crt DigiCertCA.crt ...

  2. C++子类的构造函数

    子类的构造函数 子类可以有自己的构造函数 子类没有构造函数,默认系统会调用父类的构造函数 子类有自己的构造函数,系统会先运行父类的构造函数,随后运行子类的构造函数,对子类对象进行覆盖和拓展 即不论子类 ...

  3. AttributeError: 'EmailUse' object has no attribute 'SendMail'

    错误原因:函数名与模块名重复 解决方案:不要将函数名与模块名重复

  4. APubPlat 一款Devops自动化部署、持续集成、堡垒机开源项目、友好的Web Terminal

    嗨.很高心你能进入这里,我是zane,  在这里给你介绍一款完整的Devops自动化部署工具 APubPlat - 一款完整的Devops自动化部署.持续集成.堡垒机.并且友好的Web Termina ...

  5. 服务端apk打包教程

    本文我将给大家介绍一个 apk 打包工具 VasDolly 的使用介绍.原理以及如何在服务端接入 VasDolly 进行服务端打渠道包操作. 使用介绍 VasDolly 是一个快速多渠道打包工具,同时 ...

  6. 26种source-map看花了眼?别急,理解这几个全弄懂

    上一篇 webpack处理模块化源码 的文章中提到了 "source map",这一篇来详细说说. 有什么作用 source map 用于映射编译后的代码与源码,这样如果编译后的代 ...

  7. [go]封装go的docker镜像

    前言 多阶段封装docker镜像,使用scratch镜像,尽量减小镜像包的体积. 封装用于编译的go镜像 Dockerfile FROM golang:1.20.1 AS builder WORKDI ...

  8. 【技术积累】Linux中的命令行【理论篇】【六】

    as命令 命令介绍 在Linux中,as命令是一个汇编器,用于将汇编语言源代码转换为可执行的目标文件.它是GNU Binutils软件包的一部分,提供了一系列用于处理二进制文件的工具. 命令说明 as ...

  9. Oracle内存管理方式介绍(转载)

    "Oracle内存管理可分为两大类,自动内存管理和手动内存管理.其中手动内存管理又可分为自动共享内存管理,手动共享内存管理,自动PGA内存管理以及手动PGA内存管理.本文会简单的介绍不同的内 ...

  10. 【opencv】传统目标检测:HOG+SVM实现行人检测

    传统目标分类器主要包括Viola Jones Detector.HOG Detector.DPM Detector,本文主要介绍HOG Detector与SVM分类器的组合实现行人检测. HOG(Hi ...