使用Python+R做用戶購買路徑分析

1、需求:

在用戶行為分析中重要的一環(huán)是對用戶行為路徑的分析,如先訪問什么再訪問什、現(xiàn)購買什么再購買什么。找到用戶的訪問或購買路徑,有助于我們對商業(yè)流程的理解,也可以幫助我們改善和優(yōu)化企業(yè)產(chǎn)品。

2、題設(shè):

假設(shè)我們是一家家電電商網(wǎng)站,擁有所有客戶的購買每種家電的詳細(xì)記錄(包括客戶id,購買產(chǎn)品,購買日期)。

客戶購買記錄,數(shù)據(jù)全是瞎編的

我們希望通過這個(gè)數(shù)據(jù)分析出社會(huì)用戶在購買家電先后順序的行為路徑。
這個(gè)結(jié)果的實(shí)際用途,例如客戶在裝修新房后購置抽油煙機(jī),那么我們很可能希望給他推薦熱水器或者空調(diào)等。我們總不至于像某東網(wǎng)站一樣,客戶購買了一個(gè)冰箱后還給推薦另一個(gè)冰箱吧?

3、結(jié)果示例:

希望能夠得到類似下圖的結(jié)果:

結(jié)果示例

這是百度echarts的Sankey(?;鶊D)圖示例,我們將通過Python+R實(shí)現(xiàn)類似的效果。

4、技術(shù)路線:

如標(biāo)題所述,使用Python進(jìn)行數(shù)據(jù)處理,形成R繪圖直接可用的數(shù)據(jù)結(jié)構(gòu);再使用R繪制Sankey圖(之所以不使用Python直接繪圖,是因?yàn)镻ython在繪制桑基圖方面還不夠完善——好吧,是我不會(huì)!)。
先來看R繪制桑基圖networkD3官方給出的示例代碼:

#R code
# Load energy projection data
# Load energy projection data
URL <- paste0(
        "https://cdn.rawgit.com/christophergandrud/networkD3/",
        "master/JSONdata/energy.json")
Energy <- jsonlite::fromJSON(URL)
# Plot
sankeyNetwork(Links = Energy$links, Nodes = Energy$nodes, Source = "source",
             Target = "target", Value = "value", NodeID = "name",
             units = "TWh", fontSize = 12, nodeWidth = 30)

訪問上述url指向的地址,可以看到數(shù)據(jù)文件格式,這是一個(gè)json文件,結(jié)構(gòu)如下:

#R networkD3繪制?;鶊D所需的數(shù)據(jù)格式
{"nodes":[
{"name":"Agricultural 'waste'"},
{"name":"Bio-conversion"},
……
],
"links":[
{"source":0,"target":1,"value":124.729},
{"source":1,"target":2,"value":0.597},
{"source":1,"target":3,"value":26.862}],
……
]}

數(shù)據(jù)主要包含兩個(gè)部分:nodes的每條記錄表示?;鶊D中每個(gè)節(jié)點(diǎn)位置的名稱;links的每條記錄表示從某個(gè)節(jié)點(diǎn)到另一個(gè)節(jié)點(diǎn)出現(xiàn)的次數(shù)。source和target后面所跟的數(shù)字順序和nodes后面的數(shù)據(jù)順序一致。如0表示節(jié)點(diǎn)名字是Agricultural 'waste',1表示節(jié)點(diǎn)Bio-conversion,{"source":0,"target":1,"value":124.729}表示從Agricultural 'waste'到Bio-conversion有124.729大的量。
因此,剩下的工作就是如何將上述分筆交易數(shù)據(jù)轉(zhuǎn)化成上述符合要求的格式。

5、數(shù)據(jù)整理:

大致分析一下,我們首先需要找到購買了兩筆及以上的客戶。然后將這些客戶中,每個(gè)客戶成交商品的順序進(jìn)行處理。
如一個(gè)客戶先后購買了:冰箱——洗衣機(jī)——電視機(jī),整理出的關(guān)系則是:

source    target    value
冰箱       洗衣機(jī)     1
洗衣機(jī)     電視機(jī)     1

(1)首先,需要將購買有2次記錄及以上的所有數(shù)據(jù)篩選出來備用。

#Python code
import pandas as pd
#讀取所有數(shù)據(jù)
base_data=pd.read_excel('C:/Users/Administrator/Desktop/家電購買記錄.xlsx')
#找出購買了兩次及以上的用戶(通過user_id統(tǒng)計(jì)次數(shù)再作篩選)
buy_times=base_data.groupby('user_id')['product'].count()
re_buy_userid=buy_times[buy_times>1].reset_index()
#篩選所有購買兩次及以上用戶的購買記錄
rebuy_data=base_data[base_data['user_id'].isin(re_buy_userid['user_id'])]

(2)第二步,分析購買先后次序。思路是對每個(gè)客戶的購買記錄進(jìn)行分析,形成第5部分開頭所示的明細(xì)列表,然后再對這個(gè)明細(xì)列表進(jìn)行匯總,計(jì)算出每種對應(yīng)關(guān)系的匯總結(jié)果。

#Python code
#分析流向
source_name=[]
target_name=[]
num=[]
#遍歷每個(gè)購買兩次及以上的用戶id
for user_id in re_buy_userid['user_id']:
    #取出每個(gè)用戶購買記錄明細(xì),按時(shí)間升序排列,重建索引,以便后面取結(jié)果時(shí)使用
    each_buy=rebuy_data[rebuy_data['user_id']==user_id].sort_values(by='buytime',ascending=True).reset_index()
    #按順序?qū)ι鲜雒骷?xì)數(shù)據(jù)進(jìn)行遍歷,分別取當(dāng)前記錄的product和下一條記錄的product,即可構(gòu)成購買先后關(guān)系
    for i in range(len(each_buy)-1):
        each_source=each_buy['product'][i]
        each_target=each_buy['product'][i+1]
        source_name.append(each_source)
        target_name.append(each_target)
        num.append(1)
#對結(jié)果進(jìn)行整理,形成一個(gè)表格
st_result=pd.DataFrame([source_name,target_name,num],index=['source_name','target_name','num']).T
#獲取統(tǒng)計(jì)結(jié)果
group_result=st_result.groupby(['source_name','target_name']).count().reset_index().sort_values(by='num',ascending=False)

這里我們得到的結(jié)果如下:

客戶購買路徑數(shù)據(jù)統(tǒng)計(jì)結(jié)果

實(shí)際上,到這里,基本上已經(jīng)是我們R所需要的數(shù)據(jù)了,只需要將其轉(zhuǎn)換成json格式即可。
同時(shí),我們可以得出結(jié)論:我們的客戶通常情況下買了電視機(jī)會(huì)接著買空調(diào),買了電飯鍋通常會(huì)買電磁爐,買了空調(diào)通常會(huì)買微波爐(千萬別拿這個(gè)當(dāng)決策,前面說了數(shù)據(jù)都是我瞎編的)...
(3)第三步,將上述數(shù)據(jù)轉(zhuǎn)換成json格式,并存儲(chǔ)成文件。

#Python code
#轉(zhuǎn)化json所需格式
#定義names,以確定nodes的name順序
names=group_result['source_name'].append(group_result['target_name']).drop_duplicates().reset_index(drop=True)
#將確定好的name順序固定,生成一個(gè)對應(yīng)表,用以對group_result里面的中文補(bǔ)充相應(yīng)的name順序代號
names_order=names.reset_index().reset_index().rename(columns={'level_0':'source','index':'target',0:'product'})
#添加source_name對應(yīng)的name代號
mid_data=pd.merge(group_result,names_order[['source','product']],left_on='source_name',right_on='product',how='left')
#添加target_name對應(yīng)的name代號
path_data=pd.merge(mid_data,names_order[['target','product']],left_on='target_name',right_on='product',how='left')

#生成nodes
name_list=[]
for i in names:
    each_name={'name':i}
    name_list.append(each_name)
#生成links
source_target=[]
for i in range(len(path_data)):
    each_links={'source':path_data['source'][i],'target':path_data['target'][i],'value':path_data['num'][i]}
    source_target.append(each_links)

#生成json格式
rebuy_dict={"nodes":name_list,"links":source_target}
rebuy_json=str(rebuy_dict).replace("'",'"')

#存儲(chǔ)為json格式
f=open("d:/rebuy.json","w",encoding="utf-8")
f.write(str(rebuy_json))
f.close()

(4)第四步,使用R繪圖

#R code
library(networkD3)
rebuy <- jsonlite::fromJSON('D:/rebuy.json')
sankeyNetwork(Links = rebuy$links, Nodes = rebuy$nodes, Source = "source",
              Target = "target", Value = "value", NodeID = "name",
              units = "TWh", fontSize = 30, nodeWidth = 30,
              fontFamily = "微軟雅黑")

來看結(jié)果吧:

客戶購買路徑圖

不能更丑了,已經(jīng)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容