前述一:本文旨在利用DAX在Power BI實現客戶購買行為的分析,並據此以洞察產品潛力。(註:本文邏輯可能有點複雜,但推薦大家研究,必有收穫)

前述二:微軟BI專家Marco Russo和Alberto Ferrari剛好就在五年前的本月在DAX Patterns上發表了關於利用DAX實現購物籃分析(也稱交叉購買分析)的文章(點此到達文章網頁),該文詳細描述瞭如何利用DAX得出任意產品組合下的訂單數量及購買客戶數量等等,以下圖為例,Customers一列顯示了不同層級及層級下的產品的購買客戶數量,Customers with Both Products則顯示了所有即購買該產品也購買了用戶在Filter Product處所選擇的產品的客戶數量(該度量值同樣也能找出是哪些客戶購買了所選定的產品組合),Customers with Both Products % 即為後者佔前者的比例,也即購買A產品和B產品的客戶的交集佔僅購買A產品的客戶的比例。

(圖片源自https://www.daxpatterns.com/basket-analysis/)

該分析有利於業務人員找出最佳的產品組合,或向特定類別的用戶推送特定組合的產品以促進銷量,該文章無論是從產品分析還是客戶分析的角度看都是十分有價值的,但本文將會基於此做更深入、面向另一種應用場景的分析,從產品的角度分析客戶的購買軌跡,我們可以知道哪些產品更具潛力,發現客戶未表露出的潛在需求。】

一、本文與購物籃分析的異同

本文與購物籃分析一樣都是通過分析用戶購買行為以及產品以獲取洞察,但區別在於,前者分析的是即A又B,而本文分析的是先買A其後購買B的客戶數及比率,以及先買B的客戶中又有多少人及多大比重的人會購買A(可參考以下對比圖)

附1:購物籃分析結果:Customers with Both Products: 72名客戶都有Bottles and Cages(單車放置水杯的卡槽)和Bike Racks(單車架)的購買記錄。

附2:本案例計算結果:(行欄位為用戶首先購買的產品子類,列欄位為用戶購買該產品子類之後所購買的產品子類,案例暫時忽略同時購買的記錄)首先購買Bike Racks的客戶中有8名在後續購買了Bottles and Cages,首先購買Bottles and Cages的客戶中有14名在其後購買了Bike Racks。

Marco的關於同時購買AB兩種產品的概率計算實際上就是針對於類似啤酒和尿布這樣的應用案例,因為這些訂單的確是一次性完成的。那些男人要完成他們妻子下達的買尿布的任務,他們也同時喜歡喝啤酒,但這是分析師依據歷史數據分析出的產品關聯性,是他們已經擁有了購買啤酒與尿布的需求,這是一個已經存在的關聯問題。但有些時候我們需要做的是挖掘客戶的潛在需求,這很大程度上是未知的。而客戶的訂單購買軌跡能夠反映一些十分有用的事實,它讓產品之間的關聯性有了方向。換句話說,不考慮訂單時間先後的購物籃分析在分析超市數據時很適用,因為用戶往往在一次購物中購買多個產品,然後到收銀臺統一下單,這種情況下所有的產品都被當做是同時下單了,但實際上顧客在超市內的選取商品的軌跡你無法追溯。但如果是在其他場景,比如顧客在電商平臺或者官網下單,你作為店長,你可能想知道的是,A和B同樣作為暢銷款,究竟哪一款能帶來更多回頭客,哪一款反而比較容易流失客戶呢?因此,我們需要知道每一款產品的回頭率,比如所有先購買A產品的顧客,他們在日後再次回來購買產品的佔比是多少,進一步分析,在這些復購的人羣中,購買的依然是A產品,還是其他的產品呢?各自的佔比又是多少,這是個值得研究的問題。

本文改用了和Macro購物籃分析中同樣的數據集和數據模型,最終計算結果如下圖所示,可以看到,先購買Road Bikes(公路自行車)後購買Mountain Bikes(山地自行車)的客戶有1853人,比率29%,而先買Mountain Bikes後買Road Bikes的客戶卻僅有200人,比率不到5%:

二、本文案例的計算邏輯

如果沒有弄清本段的計算邏輯,那麼後面所列出的DAX公式會很難看懂。上圖中的表格(矩陣)雖看似簡單,但計算量不小。每一行都經歷了一條獨立的計算過程。

以Mountain Bikes(山地自行車)那一行為例,首先購買Mountain Bikes的客戶中在後續購買了Bike Racks(單車架)、Road Bikes(公路自行車)等各產品子類的客戶分別佔所有購買Mountain Bikes的客戶的多大比例。

(註:該比率的演算法有三種,分子相同但基於不同的分母:

1.基於所有購買該產品子類的所有客戶

2.基於所有首先購買該產品子類的所有客戶

3.基於所有首先購買該產品子類其後又有回購行為的客戶

這三種演算法我都有計算,但本文以第一種為例)

計算流程為:

1.首先是在主表(Sales)中篩選出所有Mountain Bikes的訂單數據,然後進一步篩選,哪些訂單是作為客戶的首單的(對應客戶的所有訂單中下單日期最早的一個或多個訂單被歸類為首單,其餘為"非首單"),在經過此次篩選後的表中提取出客戶名單。

2.有了客戶名單後,我們需要找出這些客戶的所有除首單以外的訂單,而不僅僅是包括Mountain Bikes的訂單,這個步驟使用左外連接的方法完成(可參考下文DAX公式)。在DAX中完成這個虛擬表後,再對表中的客戶進行Distinct Count, 這將會得出首先購買Mountain Bikes的客戶中有多少人在其後又購買了其他的產品。

3.其後,我們需要使這個數據能夠被產品篩選(本案例計算的是產品子類),此處則和Macro的計算邏輯基本相同,使用一個與產品表完全相同的副本(Filter Product),和主表建立非活動關係,然後再建立一個度量值,使其上下文忽略產品表的所有欄位,並接受來自其副本(Filter Product)的上下文,使用該副本的產品子類欄位篩選此前Distinct Count的結果,即可得出首先購買Mountain Bikes的客戶中有多少人在其後分別購買了其他各個產品子類。

4.最後一步,讓該度量值除以購買Mountain Bikes的客戶總數(即按照上文所述第一種比率演算法),即可得出:在所有購買了Mountain Bikes的客戶中,有多大比例的客戶是先買Mountain Bikes而後購買其他的一些產品子類的。

此即為客戶購買軌跡分析的計算邏輯,對於產品或產品類別、產品子類的每一項,都要經歷這樣的計算流程,因此最終的結果是經歷複雜計算得出的。

三、DAX實現過程

1.新建計算列,判定客戶的首單:

IsFirstOrder =
VAR
E_Date = Sales[OrderDateKey]
VAR
CUST = Sales[CustomerKey]
RETURN
IF(
SUMX(
FILTER(Sales,
CUST = Sales[CustomerKey]&&E_Date > Sales[OrderDateKey]),
COUNTROWS(Sales))>0,FALSE,TRUE)

2.以下公式名為VT1的虛擬表即用於完成前述計算流程的步驟1,提取出了一個包含指定客戶名單的表;接下來完成步驟2,虛擬表VT2完成了一個十分關鍵的計算步驟,以Sales表為主表,使用左外連接和VT1中的客戶表關聯,然後篩選ROWS列返回結果,

(註:以完整的sales表為主表,leftjoin上一步所返回的客戶,所有[ROWS]為空的行說明這些行的客戶,並不是VT1所返回的客戶,否則[ROWS]應該為1,篩選掉那些[ROWS]為空的行,剩下的數據就是VT1所返回的所有客戶的所有訂單了)

這也是NATURALLEFTOUTERJOIN()函數的一種十分有用的應用場景。最後,篩選虛擬表VT2,使其數據排除掉所有首單數據,DISTINCTCOUNT客戶數以得出"首先購買某產品的客戶中有多少人在其後又購買了其他的產品":

CustDistinctValue =
VAR
FIRSTORDERPROD =
IF(HASONEVALUE(Product[Subcategory]),
VALUES(Product[Subcategory]),0)
VAR
VT1 =
SUMMARIZE(
FILTER(Sales,
AND(related(Product[Subcategory]) = FIRSTORDERPROD,
Sales[IsFirstOrder]=TRUE)),
Sales[CustomerKey],
"ROWS",
DISTINCTCOUNT(Sales[CustomerKey]))
VAR
VT2 =
FILTER(
NATURALLEFTOUTERJOIN(ALL(Sales),VT1),
[ROWS] = 1)
RETURN
CALCULATE(
DISTINCTCOUNT(Sales[CustomerKey]),
FILTER(VT2,Sales[IsFirstOrder] = FALSE)
)

3.該公式即用於完成前文所述步驟3,使得在步驟2所計算出的結果能夠被Filter Product的產品欄位所篩選:

CustPurchaseOthersSubcategoryAfter =
VAR CustPurchaseOthersSubcategoryAfter =
CALCULATE (
Sales[CustDistinctValue],
CALCULATETABLE (
SUMMARIZE ( Sales, Sales[CustomerKey] ),
Sales[IsFirstOrder] = FALSE,
ALLSELECTED (Product),
USERELATIONSHIP ( Sales[ProductCode],
Filter Product[Filter ProductCode] )
)
)
RETURN
IF(NOT([SameSubCategorySelection]),
CustPurchaseOthersSubcategoryAfter)

其中,SameSubCategorySelection函數用於排除選擇相同產品子類的數據,此公式引用Macro的方法完成:

SameSubCategorySelection =
IF (
HASONEVALUE ( Product[Subcategory] )
&& HASONEVALUE ( Filter Product[Filter Subcategory] ),
IF (
VALUES ( Product[Subcategory])
= VALUES ( Filter Product[Filter Subcategory] ),
TRUE
)
)

最後,算出比率,完成整個計算流程。公式中的PATTERN 1、PATTERN 2、PATTERN 3分別對應前文所述的三種比率演算法,你也可以自己使用SWITCH()實現三種比率演算法結果在前端的切換:

CustPurchaseOthersSubCategoryAfter % =
--PATTERN 1
DIVIDE ( Sales[CustPurchaseOthersSubcategoryAfter], [Customers] )
--PATTERN 2
--DIVIDE ( Sales[CustPurchaseOthersSubcategoryAfter], Sales[AsFirstOrderCust] )
--PATTERN 3
--DIVIDE ( Sales[CustPurchaseOthersSubcategoryAfter], Sales[AsFirstOrderCustRepurchase])

結果如下圖所示,經隨機抽取部分數據驗證無誤:

四、結果與可視化

該分析的可視化使用名為Chord的可視化控制項,可以看出,先購買自行車的客戶有很多人在其後購買瞭如Helmets(頭盔)之類的騎行裝備或單車部件,而先購買Helmets的客戶中沒有任何客戶在其後購買單車,當然這是符合常理的,這些客戶原本就有這類單車,當然不需要再買,因此對這類客戶推送單車很可能會造成廣告資源浪費,此外這類客戶有很大的購買除Helmets以外的其他的他們沒買過的單車裝備的需求。另一方面,表格數據反映首先購買公路自行車的客戶較先購買山地自行車的客戶具有更大的購買潛力,因此公路自行車能夠帶來比山地自行車更大比例的回頭客,如果我們使用傳統的購物籃分析,是無法發現這些隱含在AB購買中的問題的。按照這個思路以及在Power BI的實踐方式,結合實際業務場景做相應調整,能夠發現更多有價值的信息。

(註:本博文發佈於2019年6月14日,另有英文版)

End~


【Gerhard大神建議我在文章結尾處附上PBIX文件下載鏈接,並且本文所涉及的分析內容較多,實際上以上全文已經省略了部分內容,因此本文所用PBIX文件還包含部分本文未涉及到的公式。原創不易,無論你是小白還是大神,歡迎點贊分享,以鼓勵我為社區貢獻微薄之力


推薦閱讀:
相關文章