用户行为分析系列实践 14 – T+0 实时分析

目标任务

用户事件表T结构和部分数据示例如下:

Time UserID EventType OS Browser ProductID f1 f2 f3 f4 f5
2022/6/1 10:20 1072755 Search Android IE 100001 true false false true false
2022/6/1 12:12 1078030 Browse IOS Safari 100002 false false true true true
2022/6/1 12:36 1005093 Submit Android Chrome 100003 true true true false false
2022/6/1 13:21 1048655 Login Windows Chrome false false true true true
2022/6/1 14:46 1037824 Logout Android Edge false false false true true
2022/6/1 15:19 1049626 AddtoCart Windows Edge 100004 true true false true false
2022/6/1 16:00 1009296 Submit IOS Firefox 100005 false true false false true
2022/6/1 16:39 1070713 Browse IOS Sogou 100006 true true true false false
2022/6/1 17:40 1090884 Search Windows IE 100007 true false true true false

T表字段说明:

字段名 数据类型 字段含义
Time 日期时间 事件发生的时间戳,精确到毫秒
UserID 字符串 用户ID
EventType 字符串 事件类型,取值为Login,Browse,Search,AddtoCart,Submit,Logout
OS 字符串 操作系统,取值为Android,IOS,Windows,Unknown
Browser 字符串 浏览器,取值为IE,Safari,Edge,Firefox,Chrome,Sogou,Unknown
ProductID 字符串 产品ID,取值为产品维表中的ProductID字段
字符串 更多其它取值为枚举值的字段
f1 布尔值 是否异地发生,取值为真和假
f2 布尔值 是否惯用设备,取值为真和假
f3 布尔值 是否惯用浏览器,取值为真和假
f4 布尔值 是否是手机,取值为真和假
f5 布尔值 是否首次操作,取值为真和假
布尔值 更多其它取值为真和假的字段

维表Product:

ProductID ProductName Unit Price ProductType
100001 Apple Pound 5.5 Fruits
100002 Tissue Packs 16 Home&Personalcare
100003 Beef Pound 35 Meat
100004 Wine Bottles 120 Beverage
100005 Pork Pound 25 Meat
100006 Bread Packs 10 Bakery
100007 Juice Bottles 6 Beverage

维表Product字段说明:

字段名 数据类型 字段含义
ProductID 字符串 产品ID
ProductName 字符串 产品名称
Unit 字符串 销售单位
Price 数值 单价
ProductType 整数 产品类别

计算任务:

统计指定时间段内,产品类别为Home&Personalcare,本地使用安卓/苹果手机,使用Safari/ Edge/ Chrome,且非首次操作的用户,在最近三个月内依次发生过搜索、加购物车、提交订单这三个动作中前N个的用户数量,从而方便后续统计用户转化率和用户流失率,即漏斗转化分析。

需要注意的事项:时间窗口为最近三个月,要包含最新发生的数据。其它事项和前述漏斗分析一致:

1、 上述三个事件必须按时间顺序依次发生,顺序不对的不算

2、 上述三个事件必须是同一个用户在时间窗口期内发生,超出时间窗口期则不算

3、 以第一个事件发生时间点开始计时,如果后续事件在时间窗口期内按顺序发生,则相应事件记为1次,否则为0次,一旦出现某个事件为0次,后续事件就不用继续扫描。

实践技能

历史数据根据前面文章的介绍,输出到T.ctx中,最新的实时发生的数据,利用append@y()函数,实时追加到内存的补区中,参与实时分析计算,这部分数据不会写入组表文件,不会干扰组表文件的正常存储和定期追加。

虚表和组表、复组表均支持append@y()函数

示例代码

1、 参考前述文章的介绍,将历史数据存入T.ctx组表文件中,按年月分表存储,形成复组表

2、 在复组表的基础上定义虚表,代码和上一篇文章一样


A
1 =to(2021,2022).conj((a=~*100,12.(~+a)))
2 =T("Product.btx").keys@i(ProductID)
3

=[{file:"T.ctx",

zone:A1,

user:"UserID",

date:"Time",

column:[

{name:"Month",exp:"month@y(Time)"},

{name:"EventType",pseudo:"EventTypeName",enum:["Login","Browse","Search","AddtoCart","Submit","Logout"]},

{name:"OS",pseudo:"OSName",enum:["Android","IOS","Windows","Unknown"]},

{name:"Browser",pseudo:"BrowserName",enum:["IE","Safari","Edge","Firefox","Chrome","Sogou","Unknown"]},

{name:"b1",bits:["f1","f2","f3","f4","f5"]},

{name:"ProductID",dim:A2}]

}]

4 =pseudo(A5)

3、 把实时新数据读出来,然后按UserID,Time排序,通过append@y()追加到复组表的内存补区中

这里假设每天0点以后会把头一天的数据追加到复组表的文件中,所以实时新数据就是当天早晨0点之后的数据。


A
/前面定义虚表的代码
5 =connect("demo").cursor@x("select * from T where Time>=? order by UserID,Time",date(now()-1))
6 =A4.append@y(A7)

A5 连接数据库,读取T表的当天新数据的并产生游标, 数据要按UserID,Time排序

A6 将游标数据读出通过虚表追加到复组表的内存补区中

如果不使用虚表,直接打开复组表用append@y()追加也可以,那就要参考前面的文章,对枚举字段先进行序号化以及对二值字段进行位维转换。

4、 利用虚表进行数据统计,代码和上一篇文章一样,SPL会自动把内存里的实时数据和复组表文件里存储的数据归并按正确的方式输出


A B C D
/前面定义虚表的代码
5 >start =elapse@m(now(),-3),tw=7
6 [Search,AddtoCart,Submit] =A6.(0)
7 =A4.cursor(UserID, EventType,Time;Time>=start && A6.contain(EventType) && ProductID.ProductType=="Home&Personalcare"&& ["Safari","Edge","Chrome"].pos(BrowserName) && ["Android","IOS"].pos(OSName) && ! f1 && f4 && !f5)
8 for A7;UserID =first=A8.select@1(EventType==A6(1))
9
if(B8==null) next
10
=t=null =A6.(null)
11
for A6 if #B11==1 >C10(1)=t=t1=first.Time
12

else >C10(#B11)=t=if(t,A8.select@1(EventType==B11 && Time>t && Time<elapse(t1,tw)).Time,null)
13
=C10.(if(~,1,0))
14
>D6=D6++B13
15 return D6

5、 如果不采用双维有序的复组表,做法和上述一样,也是通过append@y()把数据追加到组表的内存补区中,统计代码不需要改变。

运行结果:

Member
393400
257539
83375