Spark实现电商消费者画像案例

news2024/9/20 16:32:52

作者/朱季谦

故事得从这一张图开始说起——

可怜的打工人准备下班时,突然收到领导发来的一份电商消费者样本数据,数据内容是这样的——

消费者姓名|年龄|性别|薪资|消费偏好|消费领域|常用购物平台|常用支付方式|单次购买商品数量|优惠券获取情况|购物动机

Mario Johnston,53,男,12510,性价比,母婴用品,网易考拉,信用卡,2,折扣优惠,兴趣爱好
Daniel Cooper,28,男,11891,社交影响,图书音像,京东,信用卡,1,折扣优惠,兴趣爱好
Amber Powell,28,女,3365,环保可持续,食品饮料,苏宁易购,货到付款,1,折扣优惠,日常使用
Olivia Fletcher,32,女,3055,环保可持续,食品饮料,天猫,银联支付,7,满减优惠,日常使用
William Wood,32,男,13492,创新设计,电子产品,网易考拉,货到付款,9,有优惠券,商品推荐
Sarah Bell,36,男,17791,创新设计,家居用品,亚马逊,微信支付,1,免费赠品,商品推荐
Cynthia Grant MD,65,男,17847,品牌追求,服装,唯品会,支付宝,3,有优惠券,跟风购买
......

这份数据样本总共五千多条,打工人害怕弄丢了,他决定先上传到百度网盘,放在这个网盘地址里——

链接: 百度网盘 请输入提取码 提取码: wjgw

存好数据后,打工人去跟领导讨论一下需要分析哪些画像,领导给了一下几个思路——

年龄和性别画像:根据用户的年龄和性别信息,了解不同年龄段和性别分布情况。
购物平台和支付方式画像:了解用户首选的电商平台和支付方式,有助于针对不同渠道进行个性化的营销活动。
优惠偏好画像:通过用户在折扣优惠、免费赠品等方面的选择,可以了解其在购物时最看重哪些优惠方式。
商品类别偏好画像:根据用户对汽车配件、珠宝首饰、图书音像等不同商品类别的选择,可以推测用户的兴趣爱好和消费倾向。
购物目的画像:通过用户对商品的描述,如性价比、时尚潮流、环保可持续等,推断其购物的目的和价值观。

接下来,就是基于这些数据和分析目标,开始基于Spark实现电商用户画像案例讲解。

在线上生产环境里,样本数据一般会放到HDFS或者HBase等地方,这些数据可能还会进一步清洗后同步到Hive里,方便直接Hive SQL或者Spark-SQL方式读取到做计算。本次代码案例里,暂时不需要涉及那么复杂的存储,只需了解真实生产线上数据是放HDFS、HBase等仓库存储即可。

一、本地样本文件的存放和读取清洗

把样本文件consumers.csv放到项目里路径为src/main/resources/consumers.csv,通过Spark读取到内存当中,顺便打印看下读取到的数据情况——

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/consumers.csv"
  val fileRDD = ss.sparkContext.textFile(filePath)
}

打印的结果如下所示——

Gary Mcpherson,37,女,11936,个性定制,食品饮料,京东,支付宝,4,折扣优惠,兴趣爱好
Molly Stone,31,女,14962,时尚潮流,汽车配件,拼多多,微信支付,3,无优惠券,商品推荐
Amy Wright,65,女,12855,时尚潮流,运动健身,唯品会,信用卡,3,满减优惠,日常使用
Anna Christensen,35,男,8201,创新设计,图书音像,亚马逊,货到付款,3,满减优惠,跟风购买
Samuel Santana,23,男,5061,创新设计,汽车配件,京东,支付宝,10,折扣优惠,跟风购买
Robert Williams,25,女,3038,环保可持续,食品饮料,网易考拉,支付宝,6,有优惠券,日常使用
Christopher Brown,40,女,9087,社交影响,服装,天猫,货到付款,5,折扣优惠,跟风购买
Dale Vazquez,40,女,14648,社交影响,食品饮料,亚马逊,信用卡,2,满减优惠,兴趣爱好
......

可见,Spark读取到内存里的数据,还是原始数据格式,我们需要对其进行切割,最简单的方式,就是通过Spark的map算子,将每一行的字符串,切割后存入到数组结构里,转换的情况如下图所示——

只需要一行代码就可以实现将原始样本每一行字符数据转成数组结构——

val consumerRDD = fileRDD.map(_.split(","))

转换生成的consumerRDD里每一行数据,可以理解成是一个数组,数组索引0~10对应的字段类型如下——

原始样本处理成上图情况,后续的操作,其实就纯粹可以通过类似SQL形式来计算需要的结果了。

二、画像数据分析的实现

2.1、商品类别偏好画像

根据用户对汽车配件、珠宝首饰、图书音像等不同商品类别的选择,可以推测用户的兴趣爱好和消费倾向。

针对这个需求,可以通过以下代码实现——

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/consumers.csv"
  val fileRDD = ss.sparkContext.textFile(filePath)
  val consumerRDD = fileRDD.map(_.split(","))
  consumerRDD.map(x => (x.apply(5), 1)).reduceByKey(_ + _).sortBy(_._2, false).foreach(println)
}

打印结果如下,可见这批样本里,受消费者消费倾向最多的前TOP3,分别是服装、家居用品、图书音像——

(服装,553)
(家居用品,542)
(图书音像,539)
(珠宝首饰,535)
(母婴用品,530)
(美妆护肤,526)
(汽车配件,523)
(电子产品,506)
(食品饮料,500)
(运动健身,492)

实现的核心是通过这行代码consumerRDD.map(x => (x.apply(5), 1)).reduceByKey(_ + ).sortBy(._2, false)。

consumerRDD.map(x => (x.apply(5), 1))中的x.apply(5)是对应【消费领域】字段,表示将consumerRDD中每行元素里的消费字段做一个映射,值设置为1,代表一个人关注的消费领域。

reduceByKey(_ + _)表示将具有相同键的键值对进行合并,将键相同的值相加,生成一个新的RDD,其中每个键关联着其对应的累加值,例如服装这个key,最后累加得到553值。

sortBy(.2, false)表示是按照累加的值大小降序排序。

结合以上函数,就可以实现将consumerRDD中的数据按照【消费领域】字段,聚合出每个领域的消费者数量。

2.2、优惠偏好画像

通过用户在折扣优惠、免费赠品、品牌忠诚等方面的选择,可以了解其在购物时最看重哪些消费习惯。

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/consumers.csv"
  val fileRDD = ss.sparkContext.textFile(filePath)
  val consumerRDD = fileRDD.map(_.split(","))
  consumerRDD.map(x => (x.apply(10), 1)).reduceByKey(_ + _).sortBy(_._2, false).foreach(println)
}

打印结果如下,可以看到,在这批消费者样本里,基于日常使用、礼物赠送、商品推荐等消费方式受众最多,那么可以基于商品消费做进一步优化——

(日常使用,777)
(礼物赠送,773)
(商品推荐,762)
(兴趣爱好,750)
(品牌忠诚,750)
(跟风购买,724)
(促销打折,710)

2.3、优惠券获取情况和购物动机的关系

观察优惠券获取情况和购物动机之间的联系,探索消费者是否更倾向于使用优惠券进行购物

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/consumers.csv"
  val fileRDD = ss.sparkContext.textFile(filePath)
  val consumerRDD = fileRDD.map(_.split(","))
  //以下实现将RDD转换成类似关系型数据库表的形式
  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))
  }
  //Row里0~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 analysisResult = df.groupBy("couponAcquisitionStatus", "shoppingMotivation")
    .agg(count("*").alias("MotivationCount"))
    .orderBy(desc("MotivationCount"))
​
  analysisResult.show()
}

打印结果如下,可见,当商品同时做【折扣优惠】和【商品推荐】时,消费者数量是最多的,其次就是购买消费有【免费赠品】及出于【兴趣爱好】动机消费。针对这类情况,可以做进一步分析,进而调整营销策略。

+-----------------------+------------------+---------------+
|couponAcquisitionStatus|shoppingMotivation|MotivationCount|
+-----------------------+------------------+---------------+
|               折扣优惠|          商品推荐|            168|
|               免费赠品|          兴趣爱好|            167|
|               免费赠品|          礼物赠送|            166|
|               满减优惠|          日常使用|            166|
|               无优惠券|          兴趣爱好|            165|
|               免费赠品|          商品推荐|            162|
|               免费赠品|          跟风购买|            160|
|               免费赠品|          日常使用|            159|
|               折扣优惠|          跟风购买|            158|
|               有优惠券|          礼物赠送|            157|
|               免费赠品|          促销打折|            157|
|               折扣优惠|          品牌忠诚|            157|
|               无优惠券|          日常使用|            156|
|               有优惠券|          日常使用|            156|
|               满减优惠|          礼物赠送|            155|
|               有优惠券|          品牌忠诚|            154|
|               免费赠品|          品牌忠诚|            154|
|               满减优惠|          商品推荐|            154|
|               无优惠券|          跟风购买|            153|
|               折扣优惠|          礼物赠送|            151|
+-----------------------+------------------+---------------+

以上是一些简单的实现,在真实环境里,并不会这么简单,可能还会涉及一系列数据的清洗和join处理,进而通过一些模型及算法,计算出更多有价值的画像数据。

样本处理完后,原以为这个故事结束了,打工人可以下班了,没想到——

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1911769.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Sentinel-1 Level 1数据处理的详细算法定义(二)

《Sentinel-1 Level 1数据处理的详细算法定义》文档定义和描述了Sentinel-1实现的Level 1处理算法和方程,以便生成Level 1产品。这些算法适用于Sentinel-1的Stripmap、Interferometric Wide-swath (IW)、Extra-wide-swath (EW)和Wave模式。 今天介绍的内容如下&…

【1.3】动态规划-解码方法

一、题目 一条包含字母A-Z的消息通过以下映射进行了编码: A -> 1 B -> 2 ... Z -> 26 要解码已编码的消息,所有数字必须基于上述映射的方法,反向映射回字母&…

Nacos2.X 配置中心源码分析:客户端如何拉取配置、服务端配置发布客户端监听机制

文章目录 Nacos配置中心源码总流程图NacosClient源码分析获取配置注册监听器 NacosServer源码分析配置dump配置发布 Nacos配置中心源码 总流程图 Nacos2.1.0源码分析在线流程图 源码的版本为2.1.0 ,并在配置了下面两个启动参数,一个表示单机启动&#…

C++初探究(2)

引用 对于一个常量,想要将其进行引用,则使用普通的引用相当于权限扩大(常量为只读,但此处的引用参数为可读可写),C编译器会报错. 例如: const int a 10;int& ra a;//权限放大&#xff0…

使用Mplayer实现MP3功能

核心功能 1. 界面设计 项目首先定义了一个clearscreen函数,用于清空屏幕,为用户界面的更新提供了便利。yemian函数负责显示主菜单界面,提供了包括查看播放列表、播放控制、播放模式选择等在内的9个选项。 2. 文件格式支持 is_supported_f…

详解TCP和UDP通信协议

目录 OSI的七层模型的主要功能 tcp是什么 TCP三次握手 为什么需要三次握手,两次握手不行吗 TCP四次挥手 挥手会什么需要四次 什么是TCP粘包问题?发生的原因 原因 解决方案 UDP是什么 TCP和UDP的区别 网络层常见协议 利用socket进行tcp传输代…

淮北在选择SCADA系统时,哪些因素会影响其稳定性?

关键字:LP-SCADA系统, 传感器可视化, 设备可视化, 独立SPC系统, 智能仪表系统,SPC可视化,独立SPC系统 在选择SCADA系统时,稳定性是一个关键因素,因为它直接影响到生产过程的连续性和安全性。以下是一些影响SCADA系统稳定性的因素: 硬件质量…

如何在 CentOS 上配置本地 YUM 源

引言 CentOS 作为一个流行的企业级 Linux 发行版,依赖 YUM(Yellowdog Updater, Modified)来管理软件包。YUM 源(Repository)是软件包存储和分发的中心,它们通常位于互联网上。然而,在某些情况下…

使用clion刷leetcode

如何优雅的使用clion刷leetcode 安装插件:LeetCode Editor) 插件配置: 这样我们每打开一个项目,就会创建类似的文件 我们的项目结构: 我们在题解文件中导入头文件myHeader.h并将新建的文件添加到cmakelists.txt文件,…

数据结构双向循环链表

主程序 #include "fun.h" int main(int argc, const char *argv[]) { double_p Hcreate_head(); insert_head(H,10); insert_head(H,20); insert_head(H,30); insert_head(H,40); insert_tail(H,50); show_link(H); del_tail(H); …

c++内存管理(上)

目录 引入 分析 说明 C语言中动态内存管理方式 C内存管理方式 new/delete操作内置类型 new和delete操作自定义类型 引入 我们先来看下面的一段代码和相关问题 int globalVar 1; static int staticGlobalVar 1; void Test() { static int staticVar 1; int localVar 1…

影视行业的人工智能与-【机器学习】:案例分析

欢迎关注小知:知孤云出岫 目录 引言AI和ML在影视行业的当前应用AI和ML对影视行业的未来影响案例研究:AI生成动画视频目标工具和库数据收集模型训练视频生成 结论参考文献 引言 人工智能(AI)和机器学习(ML&#xff09…

window.matchMedia

matchMedia() 返回一个新的 MediaQueryList 对象,表示指定的媒体查询字符串解析后的结果。 const width ref(); const myFunction (x) > {if (x.matches) {// 媒体查询document.body.style.backgroundColor "yellow";width.value "yellow&quo…

JavaScript 作用域 与 var、let、const关键字

目录 一、JavaScript 作用域 1、全局作用域 2、函数作用域 3、块级作用域 4、综合示例 5、总结 二、var、let、const 1、var 关键字 2、let 关键字 3、const 关键字 4、总结 5、使用场景 一、JavaScript 作用域 在JavaScript中,作用域是指程序中可访问…

网络编程:TCP

一、tcp编程 注意 1.数据本身有顺序 2.发送和接收次数不需要对应 3. 1. C/S 模式 》服务器/客户端模型 server:socket()-->bind()--->listen()-->accept()-->recv()-->close() client:socket()-->connect()-->send()-->close(); int on 1; setso…

如何学好C++?

首先,对于零基础的想学习C的同学,我想要你们先明白一件事:C是一门极为复杂且难以掌握的编程语言。因此推荐在学习C之前可以先去学习C语言,在拥有了一定的知识储备和编程能力后再学习C会更加的高效和相对轻松。 下面推荐从三个方面…

源码编译安装 LAMP

目录 2.1Apache 网站服务基础 2.1.1 Apache 简介 1.Apache 的起源 2.Apache 的主要特点 2.1.2 安装 httpd 服务器 1.准备工作 2.源码编译及安装 3.确认安装结果​编辑 4.优化执行路径 5.添加 httpd 系统服务 2.2 httpd 服务器的基本配置 2.2.1 Web 站点的部…

锅总反驳李彦宏说的“不要卷模型,要卷应用”

李彦宏的观点是大家不要卷模型,要卷应用,但我认为这种看法是荒谬的。以下是24条反驳李彦宏观点的论点和论据: 模型的准确性直接决定应用的质量和用户体验: 论据:在自然语言处理、计算机视觉等领域,模型的准…

安全求交集PSI

安全求交集定义 求交集的PSI:交集可以被两方看见或其中一方看见,非交集进行保护有两方的PSI半诚实的PSI:攻击者要严格遵守协议,在此基础上得到他人的秘密是做不到的 Two-Party Semi-Honest PSI 挑战一:隐藏非交集元素…

纯前端如何实现Gif暂停、倍速播放

前言 GIF 我相信大家都不会陌生&#xff0c;由于它被广泛的支持&#xff0c;所以我们一般用它来做一些简单的动画效果。一般就是设计师弄好了之后&#xff0c;把文件发给我们。然后我们就直接这样使用&#xff1a; <img src"xxx.gif"/>这样就能播放一个 GIF …