背景
**留存分析(羣組分析,cohort analysis)**是以一段時間窗內的研究對象,觀察其在後續若干個時間窗內有指定行爲的比例變化趨勢。
留存率是一個與DAU強相關的核心指標,是反映產品生命力的重要風向標,如果留存率高、衰減速度慢,那就說明產品生命力強勁,反之則衰弱。近來在用戶增長領域出現一種論調:AARRR已過時,RARRA纔是更好的增長模型。也強調了留存率的重要性——如果用戶都不留下來,就不會給你機會做運營。
與此同時,留存分析也是一種非常常見的數據分析模型,基本上各個業務線都會研究其特定的用戶留存(當然留存分析模型不一定僅限於用戶,比如我以前在某自行車公司就研究過自行車的留存,雖然我現在已經忘了當時是在研究啥……),比如:
- 做了一個運營活動,想看參加活動的用戶留存
- 做了一個AB試驗,想對比實驗組和對照組的用戶留存
- 產品做了一次改動,想看影響範圍下的用戶留存
……
如果來一個這樣的需求,就跑一次數,那就顯得有點不夠優雅。正是因爲它重要,又常見,且模型本質和計算邏輯比較通用,所以可以把數據處理和計算的部分抽象在數據平臺上,以便用戶能夠快速高效地進行留存分析。
本文的目標在於連通底層明細數據,並支持用戶在前端上組合篩選條件來自定義羣組,然後自動計算羣組的日、周、月留存,並在此基礎上擬合一個留存率衰減模型,以此來預測羣組在任意一天的留存值。整體思路如下:
數據分析方法
留存率計算方法
在數據倉庫日常生產調度中,有一種計算留存率的方法,即拿1個分區的基準明細數據不斷左關聯後續N個時間窗分區的明細數據,以計算重合數,進而計算留存率——這是一種穩妥的數據生產調度方法,卻有失靈活。
本文計算的方法如下:
基準表與行爲表按id關聯,日期不作限制,即同id按日期作笛卡爾積,得到的中間表如下示意——
基準日 | 用戶id | 行爲日 | 日期差 |
---|---|---|---|
2019-09-01 | user1 | 2019-09-02 | 1 |
2019-09-01 | user1 | 2019-09-03 | 2 |
2019-09-01 | user1 | 2019-09-04 | 3 |
2019-09-01 | user2 | 2019-09-02 | 2 |
2019-09-01 | user3 | 2019-09-05 | 4 |
先去重,然後按基準朱和日期差分組統計行數,得到的中間表如下示意——
基準日 | 日期差 | 用戶數 |
---|---|---|
2019-09-01 | 0 | 1000 |
2019-09-01 | 1 | 500 |
2019-09-01 | 2 | 300 |
2019-09-02 | 0 | 900 |
2019-09-02 | 1 | 400 |
再作行列轉換——
基準日 | 0 | 1 | 2 | 3 | 4 |
---|---|---|---|---|---|
2019-09-01 | 1000 | 500 | 300 | 200 | 100 |
2019-09-02 | 900 | 400 | 250 | 150 | 90 |
2019-09-03 | 1200 | 600 | 400 | 200 | 100 |
其中0那一列則是基準值,也是分母,後面各列除以基準值則可得到留存率;例如1列除以0列則是次日留存率,7列除以0列則是7日留存率。向量化計算,則可快速得出每一天的留存率。
周、月留存率計算同理。
留存冪函數擬合
就拿新增活躍舉例,一個正常的互聯網產品,觀察某一天的新增用戶,在後續N天的留存率,它總體上一定是以斜率逐步下降的速率在逐步衰減,然後到達平衡——如果把散點圖畫出來看,很容易看到長得很像冪小於0的函數曲線。
於是就可以用冪函數來擬合留存率模型,然後就可以用戶預測留存率了。
其中y是留存率,x是往後的天數,a是次日留存率(當x=1時,y = a),b是衰減冪。
從這個公式中可以看出:
- 次日留存率很重要,它決定了留存衰減曲線的起點和整體高度
- 衰減冪b小於0,b越大(越接近0)則衰減越慢,留存越穩定;b越小(絕對值越大),則衰減越快,越容易流失。
在這個公式中,x,y和a在訓練集中都是已知的,就只需要擬合b;兩邊取對數,就能把這個冪函數模型轉化成線性模型,然後用線性模型的擬合方法即可,十分簡單。
> get_fit_power <- function(x,y){
+ a <- log(x)
+ b <- log(y) - log(y[1])
+ fit <- lm(b~a)
+ return(fit$coefficients[2])
+ }
>
> # 構造樣例數據來驗證一下
> x <- 1:100
> y <- rnorm(1)*x^(-0.56234) # 係數怎麼取不重要,冪隨便瞎寫一個
> get_fit_power(x,y)
a
-0.56234
拿完全的冪函數樣本數據去擬合,擬合的結果完全吻合樣本上的冪,毫無誤差,哈哈哈。
有了上述2個數據分析方法,就可以進行數據產品建設了。
數據產品示意
(本文中的示例數據來自於網絡上某產品的數據,其中用戶id作去隱私處理。)
上傳基準明細數據
第一步沒有別的,還是上傳數據。上傳一份用戶粒度的新增明細數據,其中日期和用戶id必備,其他維度可加可不加,主要用來篩選用。
控件說明
- 第1個上傳框用於上傳行爲明細數據
- 第2個日期區間選擇器用於選定一段基準日期,即只看這一段日期以內新增的留存率情況
- 第3個和第4個下拉框只有當2份數據都上傳後才能篩選,取值範圍爲2個表列名的交集(所以2個表的日期和ID必須同名),通過用戶篩選,用來告訴用戶哪個字段是日期,哪個字段是ID,才能讓系統正確地關聯計算
- 第5個是統計週期,有
daily
(默認)、weekly
和monthly
3個值可選,分別對應日留存、周留存和月留存 - 最後一個日期單選器,用於在留存冪函數模型擬合出來以後,指定1天,計算基準日期內的新增在指定天的留存預測值
留存率熱力圖
2份數據都上傳後,指定日期字段爲day
,關聯ID爲userid
,統計週期爲daily
,則可自動計算並以熱圖形式可視化出統計週期內每1天的新增在後續的逐日留存率。這是一個標準的下三角形,每一個熱塊代表着某一個基準日在後續時間窗的留存率,顏色從淺到深表示留存率從小到大,鼠標移到一個熱塊上,可以顯示對應的基準日期、時間窗間隔,以及對應的留存率。
當然你可能覺得這樣會逼死密集恐懼症,沒有關係,可以縮小要觀察的基準日期範圍,比如我只想看8月內的留存率——
當然你可能還是覺得密集,不想看那麼多天,沒有關係,可以在圖上通過縮放截取,只看你關心範圍內的留存情況——
同樣地,你可以通過切換統計週期,來觀察周留存和月留存。
通過這幾個功能,可以對留存率作全局分析,也可以發現一些異常的現象。比如下圖所示,這款產品整體留存率偏低,6月5號這一天的新增用戶,在80+天內留存率都很高(約40%+以上的水平),在88天后驟然恢復到正常水平,所以這一天的新增用戶是什麼情況?是數據出問題了,還是持續活躍了80+天的水軍?
留存衰減冪函數模型
留存熱力圖下方有2部分,左下方是留存冪函數擬合曲線
,這個是基於用戶所篩選(如果沒有選則不篩選)的基準日日期範圍內的新增用戶的留存率數據作擬合,藍色的點爲實際留存率數值,黑色的虛線爲擬合的冪函數模型曲線,圖上有擬合的模型結果;右下方是預測留存數
,是基於擬合後的冪函數模型,在用戶指定的預測留存日期(上方最後一個日期選擇器控件篩選結果)預測的數值,比如第1行的結果表示,2019-07-17這1天有999個新增用戶,在經過57天之後(即2019-09-12)將會衰減至3.78個。從曲線圖中可以看到散點的分佈並不是嚴格符合冪函數模型,所以擬合的模型效果不會很好。
當然,用戶切換基準日日期範圍後,訓練集會變化,擬合的模型結果也會跟着變。比如我這裏限定基準日期範圍爲7月下半月(2019-07-16 - 2019-07-31),來預測這一段時期內的新增用戶在8.1號的留存值。
從下面的曲線來看,這次的擬合結果較好。基於新擬合的模型預測結果,可以看到7.30號新增了147個用戶,預期2天后能留存15個。
切片留存分析
我把數據處理放在左側導航欄,表示着數據處理結果可以適用於任何模型,包括這裏的篩選,就意味着任何一個模型不僅能作用於全體數據,還能作用於用戶任意自定義的切片。比如我只想觀察“來自於渠道3,用brand_2品牌的男性用戶”的留存情況,只需在左側輸入篩選條件channel == 'channel_3', brand == 'brand_2', gender == 'male'
,系統則會自動計算展現這個羣組的留存率和留存模型。
總結
本文以留存分析爲主題,提供了一種高效的留存率計算邏輯和留存率冪函數擬合方法,並將之產品化——只需要指定2份數據集,即可自動計算出日、周和月留存,並支持自由篩選羣體範圍、觀測週期、以及時間窗長度,同時還能基於留存率數據自動擬合留存率冪函數衰減模型,並基於這個模型預測一段時間的羣組在任意1天的留存情況、
不過後續仍有2個問題需要考慮——
- 由於這套系統是在單機內存上運行,所以試驗用的是小樣本量數據。但在一款成熟產品的數據倉庫中,用戶明細數據可是很龐大的,且關於日期作笛卡爾運算,會很消耗集羣計算資源——所以真正在生產環境中,系統的穩定性、計算效率是需要考慮的問題。
- 其實留存冪函數衰減模型再往下挖,就應該是DAU預測模型了,不過這個我現在還拿不準,所以這次先不搞。