Spark计算单跳页面转换率

article/2025/6/10 17:54:16

目录

代码功能概述

关键步骤解析

数据预处理(fenzi函数):

分母计算(fenmu函数):

转换率计算:

代码优化与拓展建议

修正字段索引错误:

优化分母计算(避免collect):

数据清洗与异常处理:

性能优化:

功能扩展:

参数化配置:

改进后的代码示例


package core.reqimport org.apache.spark.rdd.RDD
import org.apache.spark.{SparkConf, SparkContext}object 单跳转换率 {def main(args: Array[String]): Unit = {val sparkConf=new SparkConf().setMaster("local").setAppName("单跳转换率")val sc = new SparkContext(sparkConf)//读取原始数据val RDD = sc.textFile("datas/user_visit_action.txt")RDD.cache()val fenzizhi = fenzi(RDD)val fenmuzhi = fenmu(RDD)fenzizhi.foreach{case ((pid1,pid2),sum)=>val i = fenmuzhi.getOrElse(pid1, 0L)println(s"页面${pid1}跳转到${pid2}的页面转换率为:"+(sum.toDouble/i))}sc.stop()}def fenzi(RDD:RDD[String])={//将数据转换结构val flatRDD = RDD.flatMap(action => {val datas = action.split("_")List((datas(1),datas(3),datas(4)))  //用户id,页面id,时间})val groupRDD = flatRDD.groupBy(_._1)val mvRDD = groupRDD.mapValues(iter => {val tuples = iter.toList.sortBy(_._3)val flowIds = tuples.map(_._2)flowIds.zip(flowIds.tail).map(t => (t, 1))})val value = mvRDD.map(_._2)value.flatMap(list => list).reduceByKey(_ + _)}def fenmu(RDD:RDD[String])={//计算分母val fenmu = RDD.map(action => {val datas = action.split("_")(datas(3), 1L)}).reduceByKey(_ + _).collect()fenmu.toMap}}
代码功能概述

该Spark程序用于计算网站页面的单跳转换率,即用户从页面A跳转到页面B的概率。核心流程包括:

  1. 读取数据:从user_visit_action.txt加载用户访问记录。
  2. 计算分子:统计每个页面对(pid1 → pid2)的跳转次数。
  3. 计算分母:统计每个页面(pid1)的总访问次数。
  4. 计算转换率:通过分子除以分母得到转换率。

关键步骤解析
  1. 数据预处理(fenzi函数)
    • 输入:每行数据格式假设为用户ID_动作类型_页面ID_时间戳
    • 处理逻辑
      • 按用户ID分组,并对每个用户的访问序列按时间排序。
      • 提取连续页面对(如A → B),并统计每个页面对的出现次数。
    • 问题:原代码中字段索引错误(datas(1)应为用户ID,datas(2)为页面ID),需修正为:
      List((datas(0), datas(2), datas(3))) // 用户ID, 页面ID, 时间戳
      
  2. 分母计算(fenmu函数)
    • 输入:同一数据集。
    • 处理逻辑:统计每个页面的总访问次数。
    • 问题:原代码中datas(3)应为页面ID(修正为datas(2))。
    • 优化:避免使用collect()将数据拉到Driver端,改用广播变量或RDD Join。
  3. 转换率计算
    • 遍历分子结果(pid1, pid2),从分母Map中获取pid1的总访问次数,计算转换率。
    • 潜在问题:分母为0时需处理(原代码已用getOrElse避免异常)。

代码优化与拓展建议
  1. 修正字段索引错误
    // 修正后的数据提取逻辑
    val flatRDD = RDD.flatMap(action => {val datas = action.split("_")if (datas.length >= 4) {List((datas(0), datas(2), datas(3))) // 用户ID, 页面ID, 时间戳} else {List() // 过滤无效数据}
    })
    
  2. 优化分母计算(避免collect
    • 使用广播变量:将分母数据广播到Worker节点,减少Driver内存压力。
      val fenmuzhiRDD = fenmu(RDD) // RDD[(pid, count)]
      val fenmuzhiBroadcast = sc.broadcast(fenmuzhiRDD.collectAsMap())
      
    • 替换collect:若数据量较大,可改用Join操作:
      val result = fenzizhi.join(fenmuzhiRDD) // Join RDD[((pid1,pid2),sum)] with RDD[(pid1,count)]
      result.foreach { case ((pid1, pid2), (sum, count)) =>println(s"页面$pid1→$pid2转换率:${sum.toDouble / count}")
      }
      
  3. 数据清洗与异常处理
    • 过滤无效记录(如字段缺失、时间格式错误)。
    • 处理分母为0的情况(如输出提示或跳过)。
  4. 性能优化
    • 分区优化:根据数据量调整Spark分区数(repartition)。
    • 缓存策略:对重复使用的RDD(如原始数据)启用缓存(cache())。
    • 避免宽依赖:减少Shuffle操作(如groupBy可能产生宽依赖)。
  5. 功能扩展
    • 多跳转换率:统计多步跳转路径(如A→B→C)。
    • 用户分群分析:按用户属性(如新用户/老用户)计算转换率。
    • Top K转换率:输出转换率最高的页面对。
    • 输出到外部存储:将结果保存为文件或写入数据库(如MySQL、Hive)。
  6. 参数化配置
    • 通过命令行参数指定输入路径、输出路径等:
      val inputPath = args(0) val outputPath = args(1)

改进后的代码示例
object SingleJumpConversionRate {def main(args: Array[String]): Unit = {val sparkConf = new SparkConf().setMaster("local").setAppName("SingleJumpConversionRate")val sc = new SparkContext(sparkConf)val inputPath = "datas/user_visit_action.txt" // 可参数化val RDD = sc.textFile(inputPath).cache() // 缓存原始数据val fenmuzhiBroadcast = sc.broadcast(fenmu(RDD).collectAsMap()) // 广播分母数据val fenzizhi = fenzi(RDD)fenzizhi.foreach { case ((pid1, pid2), sum) =>val count = fenmuzhiBroadcast.value.getOrElse(pid1, 0L)val rate = if (count == 0) 0.0 else sum.toDouble / countprintln(s"页面$pid1跳转到$pid2的转换率为:$rate")}sc.stop()}def fenzi(RDD: RDD[String]): RDD[((String, String), Long)] = {val flatRDD = RDD.flatMap(action => {val datas = action.split("_")if (datas.length >= 4) {List((datas(0), datas(2), datas(3))) // 用户ID, 页面ID, 时间戳} else {List() // 过滤无效数据}})val grouped = flatRDD.groupBy(_._1) // 按用户分组val flows = grouped.mapValues { iter =>val sorted = iter.toList.sortBy(_._3) // 按时间排序val pageIds = sorted.map(_._2) // 提取页面ID序列pageIds.zip(pageIds.tail).map { case (a, b) => ((a, b), 1L) } // 生成页面对}flows.values.flatten.reduceByKey(_ + _) // 统计跳转次数}def fenmu(RDD: RDD[String]): RDD[(String, Long)] = {RDD.flatMap(action => {val datas = action.split("_")if (datas.length >= 3) {List((datas(2), 1L)) // 页面ID(索引2)} else {List() // 过滤无效数据}}).reduceByKey(_ + _) // 统计页面访问次数}
}

http://www.hkcw.cn/article/uSiJKgorkP.shtml

相关文章

Linux进程信号

目录 信号的认识 技术应用角度的信号 信号处理函数 信号概念 信号处理 忽略此信号 执行默认处理动作 产生信号 基本操作 调用系统命令向进程发送信号 闲聊 使用函数产生信号 raise函数 abort 由软件条件产生信号 puase函数 测试 如何理解软件条件 硬件异常产…

AWTK 嵌入式Linux平台实现多点触控缩放旋转以及触点丢点问题解决

前言 最近涉及海图的功能交互,多点触摸又开始找麻烦。 在PC/Web平台awtk是通过底层的sdl2库来实现多点触摸,但是在嵌入式Linux平台,可能是考虑到性能原因,awtk并没有采用sdl库来做事件处理,而是自己实现一个awtk-lin…

电脑重装或者开机出现错误

电脑重装或出现如下错误,遇到的错误信息表明在安装Windows时计算机意外重启或遇到错误,导致安装无法继续,怎么解决,以以下这个电脑举例 按shiftf10出现窗口 输入regedit回车 依次找到以下路径 HKEY_LOCAL_MACHINE/SYSTEM/SETUP…

印军方首次证实有战机被击落 损失数目不详引发关注

印度军方首次证实其在5月份与巴基斯坦的冲突中损失了数量不明的战斗机,同时表示这场为期四天的冲突从未接近核战争爆发点。印度国防参谋长阿尼尔乔汉在新加坡出席香格里拉对话会期间接受采访时说:“重要的并非飞机被击落,而是它们为什么会被击落。”他否认了巴基斯坦方面关于…

为什么当年梅西、内马尔、姆巴佩在巴黎拿不到欧冠,现在球队没有他们反而能夺冠? 青春风暴的胜利

北京时间6月1日凌晨,欧洲冠军联赛决赛落下帷幕。巴黎圣日耳曼队以5比0战胜国际米兰,历史上首次夺得欧冠冠军,并实现了赛季三冠王(法甲、法国杯、欧冠)。多年来,“大巴黎”一直是石油足球和金元足球的代表,坚持“超级巨星路线”,但无论是姆巴佩、梅西还是内马尔都未能带…

【C++】 类和对象(上)

1.类的定义 1.1类的定义格式 • class为定义类的关键字,后跟一个类的名字,{}中为类的主体,注意类定义结束时后⾯分号不能省 略。类体中内容称为类的成员:类中的变量称为类的属性或成员变量;类中的函数称为类的⽅法或 者成员函数。…

Spring之循环依赖源码解析

在学习Spring源码流程解析之前,首先要清楚什么是循环依赖,怎么解决循环依赖再去跟着源码学习一遍,更能加深印象。Mark

贾乃亮晒与甜馨端午节合照 父女笑容神同步

5月31日,贾乃亮在社交媒体上晒出与女儿甜馨的端午节合照,并提问大家猜猜他和甜馨吃的是甜粽还是咸粽。有网友评论说,两人的脸看起来非常相似,就连笑容都很像。甜馨,本名贾云馨,2012年10月23日出生于北京,是演员贾乃亮与李小璐的女儿。2014年4月,她与父亲一起参加了明星…

外交部深夜发声:勿要玩火 坚决反对美方消极言论

6月1日,外交部发言人就美国防长赫格塞思在香格里拉对话会上的涉华消极言论回答了记者提问。有记者问,5月31日,美国防长赫格塞思在香格里拉对话会上发表演讲,大肆渲染中国威胁,并就涉台、南海等问题发表消极言论。对此,中方表示强烈不满和坚决反对,已向美方提出严正交涉。…

零跑汽车5月交付量45067辆 增速超148%

6月1日,据零跑汽车公众号消息,2025年5月,零跑汽车单月交付量45067辆,增速超148%。连续三个月稳居造车新势力领先地位。责任编辑:zx0176

债市全年低点出现在何时 8月和12月规律探析

自2019年降息周期以来,10年国债收益率的全年低点容易出现在8月和12月。这背后的原因可以从基本面、政策面、资金面及机构行为等角度进行分析。从基本面来看,2019年以来,从第二季度开始,GDP增速容易低于全年预期目标,PMI也容易进入下行或低于枯荣线的阶段。而政策发力可能使…

中方回应美防长涉华消极言论 坚决反对美方挑衅挑拨

6月1日,外交部发言人针对美国防长赫格塞思在香格里拉对话会上的涉华消极言论进行了回应。有记者提问称,5月31日,赫格塞思在香格里拉对话会上发表演讲,渲染中国威胁,并就台湾、南海等问题发表负面言论。发言人在回答中指出,赫格塞思无视地区国家追求和平与发展的愿望,兜售…

孟维瞻:马斯克挥一挥衣袖,带走了什么,留下了什么?

【文/观察者网专栏作者 孟维瞻】马斯克离开白宫了。尽管这是一个早就预定好的结局,但在他和特朗普两人关系热火朝天的时候,大家不是没有想过另一种结局。当然,也有很多人在期待,两个人如胶似漆的蜜月期之后是否会反目成仇。如今看来,虽然说不上是反目成仇,至少也是话不投…

南航通报飞机起飞后突然返航 电池冒烟险情妥善处置

5月31日13时许,中国南方航空发布通报称,当天CZ6850杭州飞往深圳的航班上,一名旅客携带的相机电池和充电宝出现冒烟情况。乘务组迅速采取措施,妥善处置,及时排除了安全风险。为确保乘客安全,机组决定立即返航,航班在起飞15分钟后安全降落。航空公司积极做好后续服务保障工…

浙江暴雨将持续至明天上午 需防范次生灾害

不怕七月半鬼,最怕端午水。5月31日,西湖景区一景被拍摄下来。当天下午,浙西北地区开始下雨。到晚上8时,杭州、湖州累计雨量超过了14毫米,单站点最大雨量为52.9毫米,出现在临安区龙塘山。省气象台在16时20分发布暴雨警报:受西南暖湿气流和弱冷空气影响,5月31日夜里至6月…

奇瑞董事长说降价是被绑架的 反内卷呼声高

汽车行业近期出现了对“反内卷”的强烈呼声。在5月31日的2025(第三届)未来汽车先行者大会上,奇瑞汽车董事长尹同跃针对车市价格战表示,“‘价格战’是我最不喜欢的一个词,因为我是被绑架的。”他提到销售团队会告诉他竞争对手已经采取了降价措施,这让他感到非常痛苦和违背…

go|context源码解析

文章目录 Context接口Deadline()Done()Err()Value() canceler接口ctxemptyCtxcancelCtxtimerCtxvalueCtx 基本使用cancelCtxvalueCtx 首先看一下源码对“context”的描述, When a Context is canceled, all Contexts derived from it are also canceled. 当一个Cont…

香港中乐团六月京津巡演 携多位国际艺术家献演

被誉为“民乐翘楚”的香港中乐团受邀于6月13至18日赴北京及天津举行三场“阎惠昌与香港中乐团2025”内地巡演。乐团荣幸获得中华人民共和国香港特别行政区政府驻北京办事处,及巡演赞助商李锦记国际控股有限公司全力支持,将于北京艺术中心的《笙与管风琴的…

[yolov11改进系列]基于yolov11引入高效上采样卷积块EUCB的python源码+训练源码

【EUCB介绍】 论文介绍 题目 EMCAD:Efficient Multi-scale Convolutional Attention Decoding for Medical Image Segmentation 论文地址 https://arxiv.org/pdf/2405.06880 创新点 多尺度卷积解码器:提出了一种高效的多尺度卷积注意力解码器(EMCAD&a…

oscp练习PG Monster靶机复现

端口扫描 nmap -A -p- -T4 -Pn 192.168.134.180 PORT STATE SERVICE VERSION 80/tcp open http Apache httpd 2.4.41 ((Win64) OpenSSL/1.1.1c PHP/7.3.10) |_http-server-header: Apache/2.4.41 (Win64) OpenSSL/1.1.1c PHP/7.3.10 | http-methods:…