ClickHouse用户路径分析原理及实现

在互联网数据分析钟,有一种针对用户行为路径的分析模型——路径分析。路径分析应用是对特定事件的上下游进行可视化展示并分析用户在使用产品时的路径分布情况。比如:当用户使用某APP时,是怎样从【首页】进入【详情页】的,用户从【首页】分别进入【详情页】、【播放页】、【下载页】的比例是怎样的,以及可以帮助我们分析用户离开的节点是什么。


桑基图

桑基图(Sankey diagram),即桑基能量分流图,也叫桑基能量平衡图。它是一种特定类型的流程图,在常见的互联网分析后台中,桑基图常用来当作用户路径分析的可视化。通过桑基图,我们能清晰地看到各个事件之间的用户流向。

 

这里我们先对上图的元素进行一些说明:

 app_lunch、download、#-1#为事件名,事件名后的序号表示此事件的层级;如:用户路径为app_lunch->download->#-1#,则此路径内位于第二个节点的download为图中的download2事件,路径内位于第三个节点的#-1#为图中的#-1#3事件。

    #-1#为上一层的流失用户,如#-1#2即为第一层的所有流失用户


 这里我们设置了app_lunch为起始事件,即用户的事件路径为app_lunch -> xxx -> xxx……(若只有单条路径app_lunch也算)的所有session,app_lunch1表示以app_lunch为起始事件的session数共有3405,所有数据会分别流向app_lunch2、download2、#-1#2,分别为用户路径为app_lunch->app_lunch->xxx->xxx……、app_lunch->download->xxx->xxxx……、app_lunch->#-1#(流失用户)三种路径。
桑基图实际统计的指标

从上述的例子,我们可以推导出,桑基图统计的,实际就是每个用户在每次seesion内符合条件的

用户路径

 

 

如上两图所示,我们将桑基图分为event和path两个部分,event统计每个路径,每个层级不同事件的出现次数。

    event:

以上图为例:

​ E1在第一列出现了三次,且第一列有且只有事件E1,因此桑基图 第一层 E1_node1=3。

​ E2、E3第二列各出现了一次,因此桑基图第二层 E2_node2=1,E3_node2=1

event所统计的,实际为每个${事件_层级下标}的出现次数

    path:

还是以上图为例:

​ 我们将事件以窗口形式向右滑动并两两组合,路径链所产生的路径元组为

E1->E2->E1->E1->E2->E1->E3:

​ [(E1_NODE1,E2_NODE2),(E2_NODE2,E1_NODE3),(E1_NODE3,E1_NODE4)……]

path所统计的,实际就为所有( ${事件__层级下标} , ${事件__层级下标} )事件的出现次数

数据准备

SQL统计前需要注意以下几点

  •     session的划分
  •     是否需要合并重复事件
  •     正向统计\反向统计:

        正向统计: 以xxxx事件开始
        反向统计:以xxxx事件结束
        正向、反向统计在划分用户路径时,逻辑有着些许不同

  •     桑基图的数据格式
样例数据:
2019/7/31 1:51	57	518796	453f4e089af6
2019/7/31 1:51	55	518796	cd3a3d881980
2019/7/31 1:45	57	518796	519a908d53d4

数据计算

这里以正向计算(以xxxx事件开始)为模板:

WITH 
/**参数列表
**/ $startTime AS param_start_time,$endTime AS param_end_time,$second AS param_session_time,/*session划分时间,两个事件间隔 >$second,即视为不同seesion*/'$startEvent' AS param_start_event,/*开始事件*/$filterEvent AS param_filter_event,/*eg:event in('xxx','yyyy','zzzz')*/$depth AS param_depth,/*要统计的深度,如:A->B->C->${补充的代表流失用户事件},此事件的深度便为4*//*事件排序,session划分*/toDateTime(minIf(etl_time, event = param_start_event)) AS end_event_mint,/*开始事件的最早出现时间*/arrayCompact(arraySort(x -> (x.1),/*数组按元组内的时间asc排序*/arrayFilter(x -> ((x.1) >= end_event_mint),/*过滤大于等于开始事件最早出现时间的所有事件*/groupArray((etl_time, event)) /*将用户事件与时间聚合成元组数组[(time,event),(time,event)]*/))) AS sorted_events,arrayEnumerate(sorted_events) AS event_idxs,/*[(time,event),(time,event)……] 数组的下标数组如:[(time1,event1),(time2,even2)]下标数组为[1,2]*/arrayFilter( /*过滤出按seesion划分后,每个开始节点的数组下标*/(x, y, z) -> (((z.1) >= end_event_mint) AND (y > param_session_time)),/*(y > param_session_time):若两事件间隔时间大于$second,则属于不同session*/event_idxs,/*下标数组*/arrayDifference(sorted_events.1),/*event时间比较*/sorted_events) AS gap_idxs,/*若计算为反向计算,则需要再使用arrayMap(x->x+1,arrayFilter……)包裹最外层,如果不加1的话上一个事件链的结尾事件会成为下个事件链的开始事件*/arrayMap(x -> if(has(gap_idxs, x),1, 0),event_idxs) AS gap_masks,/*切分标记*/arraySplit((x, y) -> y, sorted_events,gap_masks) AS split_events, /*数据按不同session切分*/arraySlice(arrayPushBack(event_chain_.2, '#-1#'), 1, param_depth) AS event_chain,/*每个路径结尾补充一个用户流失事件,随后按照需要的深度对数组进行切分*//*桑基图结构处理(即前文提到的path结构)桑基图结构:{source:'${事件名_层级}',target:'${事件名_层级}',value:$value}*/arrayEnumerate(event_chain) AS event_chain_idx,/*获取事件路径下标数组*/arrayPopBack(arrayMap(x -> (x, x + 1), event_chain_idx)) AS source_target_idx,/*下标数组按照从左至右的窗口两两划分eg:[1,2,3,4]->[(1,2),(2,3),(3,4),(4,5)]处理后的数组最后一条数据(4,5)为异常部分,通过函数arrayPopBack去除*/arrayPopBack(arrayMap(x -> (event_chain[x], event_chain[x + 1]), event_chain_idx)) AS source_target_event/*下标数组按照从左至右的窗口两两划分eg:[A,B,C,D]->[(A,B),(B,C),(C,D),(D,'')]处理后的数组最后一条数据(D,'')为异常部分,通过函数arrayPopBack去除*/
SELECT arrayJoin(source_target) AS t,(t.1).1 AS idx_source,(t.2).1 AS event_source,(t.1).2 AS idx_targvet,(t.2).2 AS event_target,sum(user_count) AS value
FROM 
(SELECT event_chain,uniqCombined(user_id) AS user_count,source_target_idx,source_target_event,arrayZip(source_target_idx, source_target_event) AS source_targetFROM (SELECT user_id,arrayJoin(split_events) AS event_chain_,event_chainFROM (SELECT event,user_id,etl_timeFROM test.test_tableWHERE (etl_time>=param_start_time AND etl_time<param_end_time) AND param_filter_event)GROUP BY user_id)GROUP BY event_chainHAVING (event_chain[1]) = param_start_event
)
GROUP BY t

其他代码参考:

 SELECTresult_chain,uniqCombined(user_id) AS user_count
FROM (WITHtoDateTime(maxIf(time, act = '会员支付成功')) AS end_event_maxt,  #以终点事件时间作为路径查找结束时间arrayCompact(arraySort(  #对事件按照时间维度排序后进行相邻去重x -> x.1,arrayFilter(  #根据end_event_maxt筛选出所有满足条件的事件 并按照<时间, <事件名, 页面名>>结构返回x -> x.1 <= end_event_maxt,groupArray((toDateTime(time), (act, page_name)))))) AS sorted_events,arrayEnumerate(sorted_events) AS event_idxs,  #或取事件链的下标掩码序列,后面在对事件切割时会用到arrayFilter(  #将目标事件或当前事件与上一个事件间隔10分钟的数据为切割点(x, y, z) -> z.1 <= end_event_maxt AND (z.2.1 = '会员支付成功' OR y > 600),event_idxs,arrayDifference(sorted_events.1),sorted_events) AS gap_idxs,arrayMap(x -> x + 1, gap_idxs) AS gap_idxs_,  #如果不加1的话上一个事件链的结尾事件会成为下个事件链的开始事件arrayMap(x -> if(has(gap_idxs_, x), 1, 0), event_idxs) AS gap_masks,  #标记切割点arraySplit((x, y) -> y, sorted_events, gap_masks) AS split_events  #把用户的访问数据切割成多个事件链SELECTuser_id,arrayJoin(split_events) AS event_chain_,arrayCompact(event_chain_.2) AS event_chain,  #相邻去重hasAll(event_chain, [('pay_button_click', '会员购买页')]) AS has_midway_hit,arrayStringConcat(arrayMap(x -> concat(x.1, '#', x.2),event_chain), ' -> ') AS result_chain  #用户访问路径字符串FROM (SELECT time,act,page_name,u_i as user_idFROM app.scene_trackerWHERE toDate(time) >= '2020-09-30' AND toDate(time) <= '2020-10-02'AND user_id IN (10266,10022,10339,10030)  #指定要分析的用户群)GROUP BY user_idHAVING length(event_chain) > 1
)
WHERE event_chain[length(event_chain)].1 = '会员支付成功'  #事件链最后一个事件必须是目标事件
AND has_midway_hit = 1   #必须包含途经点
GROUP BY result_chain
ORDER BY user_count DESC LIMIT 20;

参考:

1、数据分析实战训练(1)用户行为分析 - 用户漏斗&用户路径分析 - 知乎

2、用户行为路径分析(附Python代码) - 知乎

3、用户行为分析模型实践(一)—— 路径分析模型 - vivo互联网技术 - 博客园

4、clickhouse数据模型之用户路径分析_马斯特杨的博客-CSDN博客_clickhouse路径分析

5、

ClickHouse用户路径分析之桑基图-pudn.com

6、

用户行为分析模型——路径分析(一)_悟乙己的博客-CSDN博客_路径归因

 

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【GIT】git个人笔记

GIT个人手册 版本 日期 修订内容 作者 V01 2019-06-25 初稿 备注&#xff1a; 使用中不断迭代完善&#xff0c;其他人使用中有其他总结的&#xff0c;可以补充。 目录 第一章 说明 一.1.1 GIT 中文手册 一.1.2 git仓库说明(工作区、暂存区、本地仓、远程仓)1 一.1.3 g…

ES优化实战- forceMerge搜索提升测试报告

测试结论 通过测试数据能够得出以下结论。 对于历史不变的数据&#xff0c;段合并的效果是非常好的。它对普通查询&#xff08;query_string&#xff09;有着较大的提升&#xff0c;提升在10%~90%不等的效果&#xff0c;其中搜索条件命中的结果集越多&#xff0c;提升就越明显…

unity对接T.Flight Hotas 4操控杆

unity对接T.Flight Hotas 4操控杆: 注: 提示: 本篇主要说明,如何使用unity获取 T.Flight Hotas 4 传回来的各种值 获取驱动: 提示:首先要下载安装官方的驱动,用他的软件先检测一边是否能够正常运行 地址: 固件地址:https://support.thrustmaster.com/zh/product…

ES优化实战 - 小操作节省百分之三十以上的磁盘空间

通过关闭索引的 _source来节省磁盘 un_source 是去掉存储的数据。在查询的时候&#xff0c;不反回数据。数据只做索引和倒排这些。 这样做的意思是&#xff0c;只让es做检索&#xff0c;不做存储。es检索完&#xff0c;只返回一个id。然后选用Hbase这样的数据库联动。Hbase擅长…

ES 搜索优化测试 - indexSort 对检索性能提升50%

indexSort 是在写入数据的时候&#xff0c;根据某个字段做排序。我们可以理解为数据的预排序。 在检索的时候&#xff0c;假如搜索正好是根据排好序的字段做排序的&#xff0c;那么将会有 50%的 检索性能提升效果。 注意&#xff0c;不要在请求中返回 count数据总量。这样配合i…

unity中的摇杆按钮设置

摇杆设备的所有按钮都有顺序编号&#xff0c;下图按钮框内的1到16分别对应摇杆设备的各个按钮。 若要使用摇杆的某个按钮需按 joystick button 按钮编号 的格式设置。unity的按钮从0开始计算在设置的时候需要减去一个数。 下图红线框住的选项其设置表示&#xff1a;摇杆7号按钮…

【转】浅谈协方差

【转】浅谈协方差 觉得有用的话,欢迎一起讨论相互学习~ 转载自&#xff1a;http://pinkyjie.com/2010/08/31/covariance/ 作者&#xff1a;进击的马斯特 协方差矩阵 Matlab协方差矩阵

IT 常用词汇(一)

1, amend [əmend] vt. 修改&#xff1b;改善&#xff0c;改进 vi. 改正&#xff0c;改善&#xff1b;改过自新 n. (Amend)人名&#xff1b;(德、英)阿门德 2, bearer [bɛrɚ] n. 持票人&#xff1b;[建] 承木&#xff1b;[机] 托架&#xff1b;送信人&#xff1b;搬运工人 …

浅谈协方差矩阵(马斯特的斯马特生活)

统计学的基本概念 学过概率统计的孩子都知道&#xff0c;统计里最基本的概念就是样本的均值&#xff0c;方差&#xff0c;或者再加个标准差。首先我们给你一个含有n个样本的集合&#xff0c;依次给出这些概念的公式描述&#xff0c;这些高中学过数学的孩子都应该知道吧&#x…

Thrustmaster(图马思特) HOTAS Warthog 疣猪杆 读取按钮数据

我所使用的摇杆是THRUSTMASTER&#xff08;右下图所示&#xff09;&#xff0c;用于在目标追踪页面进行框选物体&#xff08;实际应用场景不涉及鼠标键盘&#xff0c;只能使用操作杆进行操作&#xff09; 1、首先&#xff0c;安装摇杆所需环境&#xff0c;winR输入cmd后&#x…

速魔与图马思特优缺点对比

速魔和图马思特优缺点对比速魔图马思特传动系统直驱双皮带最大力反馈10Nm10Nm工作电压110-240V220-240V功率360W240W快拆50mm/70mm 盘面通用特制优点1.直驱&#xff0c;没有传动装置 2.力反馈更加直接 3.回盘速度更快&#xff0c;输出力度更大&#xff0c;操控好 4.秒换方向盘 …

微软获GPT-3独家授权,OpenAI创始人马斯克:与初衷相悖

萧箫 发自 凹非寺 量子位 报道 | 公众号 QbitAI 微软获OpenAI GPT-3独家授权&#xff0c;马斯克不高兴了。 就在微软官宣GPT-3后一天&#xff0c;马斯克在社交媒体上吐槽此事&#xff1a;“这看起来像是与‘开放’相悖。OpenAI本质上已经被微软‘控制’了。” 这件事情的起因&…

张俊林:GPT-4 模型会开创哪些新的研究方向?

作者&#xff5c;张俊林知乎 整理&#xff5c;蘑菇先生学习记 分享一篇张俊林老师关于GPT-4模型会开创哪些新的研究方向的回答。 引言 在这个历史性的时刻&#xff0c;回答个问题&#xff0c;留下自己作为历史见证人的足迹。先遵循这个问题的主旨&#xff0c;写两句GPT-4开创了…

OpenAI 发布 GPT-4,有哪些技术上的优化或突破?

作者&#xff1a;张俊林 在这个历史性的时刻&#xff0c;回答个问题&#xff0c;留下自己作为历史见证人的足迹。GPT4的技术报告里很明确地指出了三个新的方向&#xff1a; 第一&#xff0c;LLM最前沿研究的封闭化或小圈子化。 技术报告里说了&#xff0c;出于竞争以及安全等方…

海康威视人证对比设备SDK-C#

SDk下载地址&#xff1a;https://www.hikvision.com/cn/download_more_570.html 本文应用场景&#xff1a;第一次进行人脸身份证的验证方式&#xff0c;之后刷脸即可得到这个用户的信息 调用的SDK为布防门禁事件&#xff0c;以下为流程图和说明 报警回调事件 实际使用&#x…

java调用海康威视人脸识别抓拍

**1.**首先下载官网的sdk开发包&#xff0c;引入HCNetSDK.java&#xff0c;里面定义了很多调用的能力集。 **2.**通过报警回调函数中的黑名单报警这个接口去实现人脸抓拍的。 3.简单来说就是写个类去实现HCNetSDK.FMSGCallBack 然后根据条件函数 case HCNetSDK.COMM_SNAP_MATCH…

对接海康威视平台拿取视频流

创建工具类 public class ArtemisUtil {private static final Logger logger LoggerFactory.getLogger(ArtemisUtil.class);static {ArtemisConfig artemisConfig new ArtemisConfig();artemisConfig.setAppKey("123");artemisConfig.setAppSecret("123"…

读取海康威视摄像头实时显示视频流

提示&#xff1a;文章用于学习记录 文章目录 前言一、设置同一网段二、密码重置三、VLC 读取视频流四、opencv 读取视频流总结 前言 摄像头一般有网线和电源线两个接口&#xff0c;如下图所示&#xff0c; 用网线将摄像头与电脑连接在一起&#xff0c;电源接口连接适配器。 …

海康威视摄像头web端开发

主要方法 1.海康威视Web开发包 这个是海康威视自己开发的web开发包&#xff0c;里面含有一些demo&#xff0c;整体版&#xff0c;分屏版等等。你可以在他的demo基础上进行二次开发&#xff0c;即使是离线只要你的摄像头和电脑都是在同一路由下&#xff0c;都是可以调用的。麻…

海康威视的工业相机的使用经历

单位&#xff08;和海康是属于一个集团的&#xff09;某一部门 选择用 NVIDIA JETSON™ TX2 海康威视工业相机 的组合来完成 某检测识别任务&#xff0c;在相机选型前用邮件咨询 海康威视工业相机对 TX2 是否支持&#xff0c;得到海康相关人员的肯定答复。 于是采购了海康威…