成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

集算示例:10行代碼解決漏斗轉(zhuǎn)換計(jì)算

企業(yè)動態(tài)
銷售過程是一個多環(huán)節(jié)的過程,哪個步驟有了過大瑕疵,都會導(dǎo)致業(yè)績急劇下滑。而診斷出哪個步驟有瑕疵,除了無形的經(jīng)驗(yàn),還有量化的診斷方式,就是今天要討論的主角:轉(zhuǎn)化漏斗模型。

銷售過程是一個多環(huán)節(jié)的過程,哪個步驟有了過大瑕疵,都會導(dǎo)致業(yè)績急劇下滑。而診斷出哪個步驟有瑕疵,除了無形的經(jīng)驗(yàn),還有量化的診斷方式,就是今天要討論的主角:轉(zhuǎn)化漏斗模型

示例數(shù)據(jù)

為了詳細(xì)討論這個漏斗的實(shí)現(xiàn)過程,我們舉一個具體的網(wǎng)上商城的例子,被分析的數(shù)據(jù)也不復(fù)雜,只有一個事件表

用戶ID:用戶編碼

事件ID:事件編碼

事件屬性:不同事件有不同屬性; json格式,{“content”:”computer”,”page_num”:1}

時間:事件發(fā)生的時間 

 

事件類型和事件屬性如下所示

ld-1

需求定義

目標(biāo)結(jié)果是獲得某個操作流程在每個操作的客戶流失率,如下圖,登錄的用戶有20000人;其中有12000人進(jìn)行了:登錄->搜索商品;其中有8000人進(jìn)行了:登錄->搜索商品->查看商品。如下圖所示:

ld-2

每個事件后都可能流失一些用戶,整個圖示就象一個漏斗形狀,所以被稱為漏斗轉(zhuǎn)換分析。

我們來研究這個運(yùn)算的一些需求點(diǎn):

針對同一個用戶,我們觀察下面這兩組數(shù)據(jù),因?yàn)槭录樞蜿P(guān)系,我們認(rèn)為1000001用戶只發(fā)生了登錄行為,而1000002的三個事件符合目標(biāo)順序,到查看商品事件才流失 

用戶ID 事件ID 事件名稱 時間
1000001 10002 登錄 2017/2/3 0:01
1000001 10004 瀏覽產(chǎn)品 2017/2/3 0:03
1000001 10003 搜索產(chǎn)品 2017/2/3 0:08
1000001 10007 生成訂單 2017/2/3 0:12
用戶ID 事件ID 事件名稱 時間
1000002 10002 登錄 2017/2/3 0:01
1000002 10003 搜索產(chǎn)品 2017/2/3 0:03
1000002 10004 瀏覽產(chǎn)品 2017/2/3 0:08

 

上面這些事件,有一些事件有必然的前后關(guān)系,比如退訂商品肯定發(fā)生在訂單付款之后,訂單付款肯定發(fā)生在生成訂單之后;而收藏商品和加入購物車就不一定誰先誰后了,退訂商品前也不一定發(fā)生評價商品的事件。這些不穩(wěn)定性背后隱藏著用戶行為,通過對一組有序事件的漏斗分析,就找到了這組行為用戶在各個階段的流失率。這是***個需求點(diǎn):事件要順序發(fā)生,且能靈活定義

第二個需求點(diǎn)是能對事件屬性自由定義條件,如brand=’APPLE’,price>10。

第三個需求點(diǎn)是定義時間段,這段時間之外的數(shù)據(jù)不在考察范圍內(nèi),如2017-02-01~2017-02~28。

第四個需求點(diǎn)仍然是和時間有關(guān),窗口時間,只有在窗口時間以內(nèi)順序發(fā)生的事件才符合要求,比如5分鐘、3個自然天;上面圖中的1000002用戶在5分鐘的窗口時間條件下,那只有前兩個事件符合要求,因?yàn)闉g覽產(chǎn)品事件遲于登錄7分鐘而超出窗口時間了。

第五個需求點(diǎn)是每個用戶只記錄一次符合要求的最長事件序列

額外多提一句,現(xiàn)實(shí)業(yè)務(wù)中發(fā)生的漏斗分析不一定和上面這些需求細(xì)節(jié)完全一致,完全有可能更復(fù)雜,更個性化,我們這里是為了容易說明問題而假定了這些需求細(xì)節(jié)。

算法詳述

因?yàn)槭录箜樞虬l(fā)生,所以我們***步應(yīng)該把數(shù)據(jù)先按照時間排序了,這樣同一個窗口期的數(shù)據(jù)就匯聚到比較集中的一塊了,而且窗口期內(nèi)數(shù)據(jù)的位置也能表示先后次序了。數(shù)據(jù)量大大超出內(nèi)存,用可以借用集算器的sortx對原始數(shù)據(jù)游標(biāo)進(jìn)行外存排序。

  A B
1 =file(fPath+”event.data”).cursor@t(用戶ID,事件ID,事件屬性,時間) /以游標(biāo)方式加載文件數(shù)據(jù)
2 =A1.sortx(時間) /用時間字段外存排序
3 =file(fPath+”eventOrdered.data”).export@b(A2) /排序結(jié)果存入目標(biāo)文件

 

最終的結(jié)果只需要每個用戶最長符合條件的事件序列的長度:代表該用戶發(fā)生流失時的***一個事件。因?yàn)椴檎业倪^程中,不確定哪個事件序列最長,所以聚合信息里會保持住多個事件序列的信息。

events:定義目標(biāo)事件順序數(shù)組:[A,B,C,D,E],事件序號分別為1,2,3,4,5

UserList:定義空序表,每個用戶的信息聚合成一條信息存入這個序表,單個用戶聚合后的信息用JSON格式說明如下

 

  1.  
  2. 用戶ID:1000001 
  3.  
  4. maxLen當(dāng)前已找到的***事件序列長度:3 
  5.  
  6. seqs多個符合要求的事件序列數(shù)組:[ 
  7.  
  8. {//***個事件序列 
  9.  
  10. 該事件序列的開始時間:2017-02-03 21:18:18 
  11.  
  12. ,該事件序列***事件序號:2 
  13.  
  14. }, 
  15.  
  16. {//第二個事件序列 
  17.  
  18. 該事件序列的開始時間:2017-02-04 08:08:08 
  19.  
  20. ,該事件序列***事件序號:3 
  21.  
  22. }, 
  23.  
  24. …… 
  25.  
  26.  
  27.  

 

在定義了上面變量的基礎(chǔ)上,寫段偽代碼來描述算法過程:

 

  1. for (按時間排好序的原始數(shù)據(jù),循環(huán)逐條處理){ 
  2.  
  3. //當(dāng)前記錄里四個個變量:當(dāng)前用戶、當(dāng)前事件、當(dāng)前時間,當(dāng)前事件屬性 
  4.  
  5. if (當(dāng)前時間不在查詢時間段內(nèi) || 當(dāng)前事件屬性不符合要求) continue; 
  6.  
  7. if (在UserList里找到當(dāng)前用戶){ 
  8.  
  9. if (maxLen == events長度) { 
  10.  
  11. continue; //已經(jīng)找到當(dāng)前用戶完整的目標(biāo)事件序列,不用處理了,直接跳過 
  12.  
  13. else { 
  14.  
  15. if (當(dāng)前事件 == events***個事件) { 
  16.  
  17. 新建一個事件序列追加入events。 
  18.  
  19. else { 
  20.  
  21. for(events){ 
  22.  
  23. //變量:事件序列=events [i] 
  24.  
  25. if (當(dāng)前事件序號 == 事件序列的***序號+1 AND 當(dāng)前時間在事件序列的窗口期內(nèi) ) { 
  26.  
  27. 事件序列的***序號增加1 
  28.  
  29.               if(事件序列的***序號>maxLen){ 
  30.  
  31.        maxLen增加1 
  32.  
  33.  
  34.  
  35.  
  36.  
  37.  
  38. else {//沒找到 
  39.  
  40. 新建當(dāng)前用戶的聚合信息,然后追加到UserList里 
  41.  
  42.  

 

 

解決方案

  1. sql或存儲過程。雖然這個計(jì)算針對單表,但過程復(fù)雜,還對數(shù)據(jù)有序性有要求,這特點(diǎn)就正好是sql的軟肋。 能用sql寫出來的人,估計(jì)是鳳毛麟角,理論上能不能寫出來也存疑。退一步講,即便是寫出來了,性能的可控又是一大難題。反正我是沒有去細(xì)研究了,假如有研究出來的同學(xué),可以反饋給我學(xué)習(xí)下。
  2. UDF?那相當(dāng)于直接用高級語言硬編碼了,代碼量可想而知(比如用Java不會少于200行),不光寫出來難度很大,以后再修改維護(hù)都是頭疼的事,這種UDF又沒什么通用性,需求變了就得重寫。
  3. MapReduce以及Spark之類的東西?MapReduce對付這種有序的運(yùn)算還真不好想。只是這個算法用Scala確實(shí)也寫得出來,也不算太長,不過,其中的問題卻是……,算了,這次先不提,以后專門細(xì)說,總之Scala是不合適。
  4. 想要一種能精確描述這個計(jì)算過程,并且描述方法符合人類自然思維習(xí)慣,并且能清楚知道每個步驟結(jié)果,并且能對步驟里的性能優(yōu)化也能精確控制,并且代碼量不大,并且代碼容易復(fù)用……! 這么多貪心的“并且”,那就只能推薦這個專門處理數(shù)據(jù)的集算器腳本語言了。直接看代碼

 

  A B C D E
1 >begin=date( string(begin), ”yyyyMMdd”)   >end=date(string(end), ”yyyyMMdd”) >dateWindow =eval( dateWindow)  
2 =create(用戶ID,maxLen, seqs).keys(用戶ID)   =now()    
3 =file(fPath+” event30.txt”) .cursor@t()   =A3.select(時間>=begin &&時間<end && events.pos(事件ID)>0 && ${filter})    
4 for C3 >user=A2.find@b( A4.用戶ID)      
5   if user ==null >if (A4.事件ID ==events(1),A2.insert(,A4.用戶ID:用戶ID,1:maxLen,[[A4.時間,1]]:seqs))    
6     next    
7   if user.maxLen ==events.len() next    
8   for user.seqs >nextXh=B8(2)+1,
time1=long(A4.時間),
time2=long(B8(1))+dateWindow, outWindow=time1>time2,
nextEvt=A4.事件ID==events(nextXh)
if(outWindow ||!nextEvt) next
9     >B8(2)=nextXh,
if(nextXh>user.maxLen, user.maxLen=nextXh),
if(nextXh==events.len(), user.seqs=null)
next A4  
10   if A4.事件ID ==events(1) >user.seqs.insert (0,[[A4.時間,1]]),
if(user.maxLen==0, user.maxLen=1)
   
11 =[A2.len()] for events.len()-1 >A11.insert(0,A11(B11)- (A2.select(maxLen==B11).len()))    
12 =interval@ms(C2, now())        

 

針對單用戶的聚合代碼是第4~10行,規(guī)模和上面的偽代碼相當(dāng),基本上就是按自然思路去寫出算法。如果用Java類語言起碼是10倍長度了,代碼長了就要翻好幾頁,看到后面就會忘了前面,而集算器的代碼很短,一屏就能呈現(xiàn)出來,整個算法過程一目了然。

如果以前沒接觸過集算器的話,可能會看不懂這些代碼,不過沒關(guān)系了,掌握任何一門語言的語法都需要一個學(xué)習(xí)過程,我稍微解釋一些關(guān)鍵點(diǎn):

變量說明:開始事件begin,結(jié)束時間end,窗口期毫秒數(shù)dateWindow,目標(biāo)事件序列events,事件屬性過濾條件filter。

A2:定義一個空序表,也就是偽代碼中的UserList。用戶ID為主鍵。

A3:定義被分析數(shù)據(jù)文件的游標(biāo),這樣多大的文件都能分批加載入內(nèi)存進(jìn)行計(jì)算了。

C3:對數(shù)據(jù)游標(biāo)進(jìn)行條件過濾,效果類比SQL語句里的where子句。

A4:從C3游標(biāo)里循環(huán)取數(shù)據(jù),每次取一行記錄做處理。

B4:用二分法從UserList里找當(dāng)前記錄的用戶。

 

第5、6行:UserList里不存在當(dāng)前用戶的處理分支,按照主鍵用戶ID順序自動找正確的位置插入。

第7行:當(dāng)前用戶已經(jīng)找到完整目標(biāo)事件序列,直接跳過。

第8~9行:已找到的多個事件序列進(jìn)行循環(huán)處理,試圖把當(dāng)前用戶信息融入某個符合條件的事件序列。融入成功,跳出到A4執(zhí)行下一條;融入失敗,執(zhí)行第10行。

第11行:用UserList計(jì)算出每個目標(biāo)事件存留的用戶數(shù),也就是漏斗需要的各層數(shù)據(jù)了。

A12:以秒為單位計(jì)算出C2執(zhí)行到A12的耗時。 

 

實(shí)現(xiàn)上面這個功能,無論用哪門語言,程序邏輯應(yīng)該沒多大變化,關(guān)鍵就是看方便程度。這段流程還算繁雜的程序,寫完之后執(zhí)行,只改了兩三處小毛病就跑通了,運(yùn)行到哪個格子發(fā)生什么錯誤;哪個格子運(yùn)算后的結(jié)果是啥都會一目了然。

ld-4

ld-5 

為了驗(yàn)證這段程序是否正確,只剩下1000001用戶如下的9條數(shù)據(jù):

用戶ID 事件ID 時間 事件屬性
1000001 10001 2017/2/3 8:11 {}
1000001 10002 2017/2/3 8:12 {}
1000001 10003 2017/2/3 8:13 {“content”: “watch”, “page_num”: 3}
1000001 10004 2017/2/3 8:14 {“brand”: “Apple”, “price”: 2500}
1000001 10005 2017/2/3 8:15 {}
1000001 10006 2017/2/3 8:16 {}
1000001 10007 2017/2/3 8:17 {“price_all”: 3500}
1000001 10008 2017/2/3 8:18 {}
1000001 10009 2017/2/3 8:19 {“how”: -1}

 

不同條件的執(zhí)行結(jié)果:

窗口期1分鐘,事件序列[10003,10004,10005],算出來***事件序號是2

ld-6

增長窗口期到5分鐘,結(jié)果是3,找到了完整的目標(biāo)事件序列。

ld-7

目標(biāo)事件序列反序[10005,10004,10003]測試,結(jié)果是1,因?yàn)椴淮嬖谶@種順序。

ld-8

修改事件屬性Huawei,結(jié)果同樣為1,因?yàn)闆]有符合條件的10004事件

ld-9

結(jié)語及預(yù)告

6萬條符合條件的記錄,聚合出3萬個用戶的事件數(shù)據(jù),耗時1.8秒。目標(biāo)數(shù)據(jù)6億條時,性能即便是線性的也需要5個小時,還很可能不是線性的,這就不能容忍了。

理論上能完成的任務(wù)在性能不達(dá)標(biāo)的情況下,等同于不能完成。實(shí)際上好些生產(chǎn)中的業(yè)務(wù)就因?yàn)楹牟黄饡r間和計(jì)算資源,不得不作罷。可以預(yù)告下我們已經(jīng)驗(yàn)證了更多優(yōu)化辦法,不僅限于修改這段程序的邏輯,還有發(fā)生在數(shù)據(jù)預(yù)處理階段的。正是在逐步優(yōu)化、反復(fù)試錯的過程中才真切體會到一個順手工具的重要性。敬請關(guān)注! 

責(zé)任編輯:龐桂玉 來源: 潤乾
相關(guān)推薦

2017-09-27 18:36:31

代碼解決數(shù)據(jù)

2018-03-15 13:31:48

潤乾LinuxGREP搜索

2022-10-28 10:18:53

代碼績效Java

2009-12-03 16:39:09

phpCB批量轉(zhuǎn)換

2017-03-06 15:01:38

Python代碼詞云

2010-03-22 15:18:27

2020-02-28 15:33:12

代碼人工智能檢測

2011-08-15 09:47:49

PHP

2021-08-02 22:56:54

漏斗分析數(shù)據(jù)

2010-01-20 14:32:12

VB.NET轉(zhuǎn)換運(yùn)算符

2017-09-01 19:49:50

Python工具地圖

2020-08-12 14:54:00

Python代碼開發(fā)

2020-03-26 12:38:15

代碼節(jié)點(diǎn)數(shù)據(jù)

2020-07-22 08:30:02

代碼開發(fā)工具

2020-08-03 09:05:48

代碼程序員案例

2020-05-26 08:32:56

Python代碼開發(fā)

2018-04-24 10:45:00

Python人工智能圖像識別

2017-09-05 08:35:09

Python可視化地圖

2011-08-18 17:32:40

Oracle存儲過程利用游標(biāo)返回結(jié)果集

2017-09-06 20:42:03

集算器臨時性計(jì)算
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 久久看精品 | 欧美精品在线播放 | 亚洲国产精品自拍 | 美女久久久久久久 | 精品国产免费人成在线观看 | 国产精品乱码一二三区的特点 | 国产乱码精品一区二区三区中文 | 99精品免费视频 | 日日操av | 欧美久久久久久 | 国产成在线观看免费视频 | 91在线精品一区二区 | 成人高清在线视频 | 免费99视频| 精品国产乱码久久久久久果冻传媒 | 国产精品毛片一区二区三区 | 欧美一区二区三区久久精品 | 欧美一级片在线观看 | 午夜欧美| 在线看av网址 | 一级黄色日本片 | 中文字幕成人av | 免费特级黄毛片 | 日韩不卡一二区 | 国产精品国产三级国产a | 天天爽综合网 | 蜜臀久久99精品久久久久野外 | 国产成人在线观看免费 | avmans最新导航地址 | 久久成人在线视频 | 色.com| 一区在线观看 | 四虎永久免费影院 | 中文字幕视频一区 | 1级毛片| 久久成人免费视频 | 中文字幕精品一区二区三区精品 | 日一区二区 | 久久精品天堂 | 色综合久久久久 | 午夜视频在线免费观看 |