一 场景分析

用户行为分析应用的场景很多,像线上网站访问统计,线下客流分析(比如图像人脸识别、wifi探针等),比较核心的指标有几个:

PV | UV | SD | SC

指标说明:

PV(Page View):网站浏览量或者商场门店的访问量
UV(Unique Visitor):独立访客数,即去重后的人数
SD(Session Duration):单次会话停留时间
SC(Session Count):会话次数

用户行为分析的原始数据通常是一系列时间离散数据,比如网站访问记录:用户在一个时间点访问了一个网页,然后又在下个时间点访问了下个网页;

这些原始数据可以抽象为:

User | Timestamp | Target

即用户在什么时间点访问了什么目标;

统计PV、UV比较简单,但是在时间离散数据的基础上,要计算SD、SC这两个指标,常用的方式是设置过期时间阈值,如果用户两次访问的时间间隔超过阈值,则认为是两次Session;然后在一次Session的所有数据中取时间最早和最晚的数据来统计本次Session Duration;

二 统计示例

输入数据

(user1, 2018-12-01 01:00:00, t1)
(user1, 2018-12-01 01:01:30, t1)
(user1, 2018-12-01 01:06:00, t1)
(user1, 2018-12-01 01:20:00, t1)
(user1, 2018-12-01 01:24:00, t1)

可以统计出

PV=5,UV=1

过期时间阈值设置为5分钟,以上数据应该统计出来2次Session,分别是:

Session1: (2018-12-01 01:00:00 到 2018-12-01 01:06:00),Duration:6分钟
Session2: (2018-12-01 01:20:00 到 2018-12-01 01:24:00),Duration:4分钟

实际处理时还要数据乱序的问题,尤其是在实时计算中,你想好怎样做了吗?

容易想到的方式是先做group然后将所有的timestamp排序后一次遍历统计出SD和SC,不过这种方式占用内存比较大,性能略差,而且只能用在离线计算中。

三 代码实现

下面给出scala实现,来见证scala的强大:

scala核心代码(一步foldLeft)

scala

  val expireInSecond = 300
def mergeTimeArray(arr1 : ArrayBuffer[(Long, Long)], arr2 : ArrayBuffer[(Long, Long)]) : ArrayBuffer[(Long, Long)] = {
if (arr1.head._1.equals(0l)) arr2
else if (arr2.head._1.equals(0l)) arr1
else (arr1 ++ arr2).sortBy(_._1).foldLeft(ArrayBuffer[(Long, Long)]())((result, item) => if (!result.isEmpty && result.last._2 + expireInSecond >= item._1) {result.update(result.length - 1, (result.last._1, math.max(result.last._2, item._2))); result} else result += item)
}

spark核心代码(2步map 1步aggregateByKey)

scala

  /**
* @param data (user, timestamp, target)
* @return (user, target, session_count, session_duration)
*/
def process(data : RDD[(String, Long, String)]) : RDD[(String, String, Integer, Double)] = {
//((user, target), timestamp)
data.map(item => ((item._1, item._3), item._2))
//((user, target), Array[(startTime, endTime)])
.aggregateByKey(ArrayBuffer((0l, 0l)))((result : ArrayBuffer[(Long, Long)], timestamp: Long) => mergeTimeArray(result, ArrayBuffer((timestamp, timestamp))), (result1 : ArrayBuffer[(Long, Long)], result2 : ArrayBuffer[(Long, Long)]) => mergeTimeArray(result1, result2))
//(user, target, session_count, session_duration)
.map(item => (item._1._1, item._1._2, item._2.length, item._2.foldLeft(0l)((result, item) => result + (item._2 - item._1)).toDouble / item._2.length))
}

测试运行

  def main(args : Array[String]) : Unit = {
val conf = new SparkConf().setAppName("UserAnalysis").setMaster("local[2]")
val sc = new SparkContext(conf)
val arr = Array(("user1", 1546054000l, "t1"), ("user1", 1546054090l, "t1"), ("user1", 1546054360l, "t1"), ("user1", 1546055200l, "t1"), ("user1", 1546055440l, "t1"))
//(user, timestamp, target)
val data : RDD[(String, Long, String)] = sc.parallelize(arr)
this.process(data).foreach(println)
}

输出

(user1,t1,2,300.0)

【原创】大叔案例分享(3)用户行为分析--见证scala的强大的更多相关文章

  1. 【原创】大叔案例分享(4)定位分析--见证scala的强大

    一 场景分析 定位分析广泛应用,比如室外基站定位,室内蓝牙beacon定位,室内wifi探针定位等,实现方式是三点定位 Trilateration 理想情况 这种理想情况要求3个基站‘同时’采集‘准确 ...

  2. 【原创】大叔案例分享(5)id打通

    经常有一些需要做id打通的场景,比如用户id打通等, 问题抽象是每条数据都可以解析出一个或多个kv pair:(id_type,id),然后需要将某一个kv pair匹配的多条数据进行merge: 比 ...

  3. 老李案例分享:MAT分析应用程序服务出现内存溢出过程

    老李案例分享:MAT分析应用程序服务出现内存溢出过程   poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.在poptest的loa ...

  4. Office 2010 KMS激活原理和案例分享

    Office 2010 KMS激活原理和案例分享     为了减低部署盗版(可能包含恶意软件.病毒和其他安全风险)的可能性,Office 2010面向企业客户推出了新的批量激活方式:KMS和MAK.这 ...

  5. Office 2010 KMS激活原理和案例分享 - Your Office Solution Here - Site Home - TechNet Blogs

    [作者:葛伟华.张玉工程师 ,  Office/Project支持团队, 微软亚太区全球技术支持中心 ] 为了减低部署盗版(可能包含恶意软件.病毒和其他安全风险)的可能性,Office 2010面向企 ...

  6. 性能调优案例分享:jvm crash的原因 1

    性能调优案例分享:jvm crash的原因   poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣,请大家咨询qq: ...

  7. mysql的"双1设置"-数据安全的关键参数(案例分享)

    mysql的"双1验证"指的是innodb_flush_log_at_trx_commit和sync_binlog两个参数设置,这两个是是控制MySQL 磁盘写入策略以及数据安全性 ...

  8. MySQL数据库详解之"双1设置"的数据安全的关键参数案例分享

    mysql的"双1验证"指的是innodb_flush_log_at_trx_commit和sync_binlog两个参数设置,这两个是是控制MySQL 磁盘写入策略以及数据安全性 ...

  9. 【案例分享】使用ActiveReports报表工具,在.NET MVC模式下动态创建报表

    提起报表,大家会觉得即熟悉又陌生,好像常常在工作中使用,又似乎无法准确描述报表.今天我们来一起了解一下什么是报表,报表的结构.构成元素,以及为什么需要报表. 什么是报表 简单的说:报表就是通过表格.图 ...

随机推荐

  1. 《React Native 精解与实战》书籍连载「React Native 源码学习方法及其他资源」

    此系列文章将整合我的 React 视频教程与 React Native 书籍中的精华部分,给大家介绍 React Native 源码学习方法及其他资源. 最后的章节给大家介绍 React Native ...

  2. svn 钩子应用 - svn 提交字符限制, 不能为空

    一.版本库钩子 1.1 start-commit  开始提交的通知 输入参数:传递给你钩子程序的命令行参数,顺序如下: 1.  版本库路径 2.  认证过的尝试提交的用户名 3.  Depth,mer ...

  3. openstack安装过程遇到的问题

    1.安装openstack官方源无法使用,使用阿里云的openstack源O版源 ##cat  openstack-ocata.repo [openstack-ocata] name=openstac ...

  4. jQuery 合成事件

    jQuery有两个合成事件—— hover() 方法和 toggle() 方法,类似ready() 方法,hover() 方法和 toggle() 方法都属于 jQuery 自定义的方法. 1.  h ...

  5. 记一次innobackupex备份恢复数据库过程

    简介:以前备份都是通过mysqldump备份数据库的,由于是逻辑备份,所以采用这种备份方式数据是很安全的,跨平台.版本都很容易.凡事有利必有弊,逻辑备份在你数据库比较大时,备份.恢复数据所耗费的时间也 ...

  6. RfcConfig 类 主要解决Tomcat 报 The valid characters are defined in RFC 7230 and RFC 3986

    tomcat 8.0以后对请求URL做了严格的过滤 就是严格按照 RFC 3986规范进行访问解析,而 RFC 3986规范定义了Url中只允许包含英文字母(a-zA-Z).数字(0-9).-_.~4 ...

  7. iOS 后台调用apns推送

    1.java调用apns推送 2.php 调用apns 推送,可借助终端

  8. python之函数初识

    一.函数的初识1.如何定义函数:def 函数名(): 代码... 例如:def my_len(): l = [1, 2, 3, 4] count = 0 for i in l: count += 1 ...

  9. Magento 2 安装数据表

    Magento 2 安装数据表 第1步:安装脚本 首先,我们将为CRUD模型创建数据库表.为此,我们需要插入安装文件 app/code/Mageplaza/HelloWorld/Setup/Insta ...

  10. 【GDOI2016模拟3.15】基因合成(回文串+性质+DP)

    [GDOI2016模拟3.15]基因合成 题意: 给一个目标串,要求从空串进行最少的操作次数变成目标串,操作有两种: 在串的头或尾加入一个字符. 把串复制一遍后反向接到串的末尾. 因为有回文操作,所以 ...