CD消費(fèi)分析自己已模仿練習(xí)了很多遍,也總結(jié)過(guò)2篇文章袭厂,但任然存在很多問(wèn)題墨吓,主要原因是自己對(duì)業(yè)務(wù)不了解、對(duì)pandas的相關(guān)操作不熟悉纹磺。
如果你已經(jīng)在其他地方見(jiàn)過(guò)CD消費(fèi)分析帖烘,把這段話看完就不用看啦。分享兩個(gè)自己在練習(xí)時(shí)遇見(jiàn)的問(wèn)題:
1橄杨、用SQL如何將新用戶秘症、回流用戶、活躍用戶讥珍、不活躍用戶進(jìn)行分層历极。
2、用SQL如何求回購(gòu)率衷佃、復(fù)購(gòu)率
3趟卸、關(guān)于1、2問(wèn)題的解決方法可看此視頻學(xué)習(xí)
當(dāng)然自己寫這篇文章的目的是為了加深印象氏义,所謂書讀百遍其義自見(jiàn)锄列,練習(xí)也是如此。
本篇文章以模仿為主,利用pandas進(jìn)行數(shù)據(jù)處理惯悠,分析用戶消費(fèi)行為邻邮。數(shù)據(jù)來(lái)源CDNow網(wǎng)站的用戶購(gòu)買明細(xì)。一共有用戶ID克婶,購(gòu)買日期筒严,購(gòu)買數(shù)量丹泉,購(gòu)買金額四個(gè)字段。
具體的分析思路可參考秦路老師七周七數(shù)據(jù)分析鸭蛙,數(shù)據(jù)下載地址摹恨、密碼g6vv
《分析步驟》
第一部分:數(shù)據(jù)類型的處理—字段的清洗
缺失值的處理、數(shù)據(jù)類型的轉(zhuǎn)化
第二部分:按月數(shù)據(jù)分析
每月的消費(fèi)總金額娶视、每月的消費(fèi)次數(shù)晒哄、每月的產(chǎn)品購(gòu)買量、每月的消費(fèi)人數(shù)
第三部分:用戶個(gè)體消費(fèi)數(shù)據(jù)分析
用戶消費(fèi)金額和消費(fèi)次數(shù)的描述統(tǒng)計(jì)肪获、用戶消費(fèi)金額和消費(fèi)次數(shù)的散點(diǎn)圖寝凌、用戶消費(fèi)金額的分布圖(二八法則)迎吵、用戶消費(fèi)次數(shù)的分布圖
散址、用戶累計(jì)消費(fèi)金額的占比
第四部分:用戶消費(fèi)行為分析
用戶第一次消費(fèi)時(shí)間寞宫、用戶最后一次消費(fèi)時(shí)間揍拆、新老客消費(fèi)比花椭、用戶分層粹湃、用戶購(gòu)買周期壹将、用戶生命周期府蛇。
第一部分:數(shù)據(jù)類型的處理—字段的清洗
導(dǎo)入常用的庫(kù):
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from datetime import datetime
%matplotlib inline #‘%’內(nèi)置的命令刹前,jupyter專有的定義泳赋,比如在pycharm不常用到,inline意思是我做好圖之后可以在html頁(yè)面的單元格進(jìn)行顯示
plt.style.use('ggplot') #更改設(shè)計(jì)風(fēng)格喇喉,使用自帶的形式進(jìn)行美化祖今,這是一個(gè)r語(yǔ)言的風(fēng)格
- 加載包和數(shù)據(jù),文件是txt拣技,用read_table方法打開千诬,因?yàn)樵紨?shù)據(jù)不包含表頭,所以需要賦予膏斤。字符串是空格分割徐绑,用\s+表示匹配任意空白符。
- 一般csv的數(shù)據(jù)分隔是以逗號(hào)的形式莫辨,但是這份來(lái)源于網(wǎng)上的數(shù)據(jù)比價(jià)特殊傲茄,它是通過(guò)多個(gè)空格來(lái)進(jìn)行分隔
columns = ['user_id','order_dt','order_products','order_amount']
df = pd.read_table("CDNOW_master.txt",names = columns,sep = '\s+')
列字段的含義:
user_id:用戶ID
order_dt:購(gòu)買日期
order_products:購(gòu)買產(chǎn)品數(shù)
order_amount:購(gòu)買金額
- 消費(fèi)行業(yè)或者是電商行業(yè)一般是通過(guò)訂單數(shù),訂單額沮榜,購(gòu)買日期盘榨,用戶ID這四個(gè)字段來(lái)分析的◇∪冢基本上這四個(gè)字段就可以進(jìn)行很豐富的分析草巡。
df.head()
- 觀察數(shù)據(jù),判斷數(shù)據(jù)是否正常識(shí)別型酥。值得注意的是一個(gè)用戶可能在一天內(nèi)購(gòu)買多次山憨,用戶ID為2的用戶在1月12日買了兩次查乒,這個(gè)細(xì)節(jié)不要遺漏。
df.info()
- 查看數(shù)據(jù)類型萍歉、數(shù)據(jù)是否存在空值侣颂;原數(shù)據(jù)沒(méi)有空值档桃,很干凈的數(shù)據(jù)枪孩。接下來(lái)我們要將時(shí)間的數(shù)據(jù)類型轉(zhuǎn)化。
- 當(dāng)利用pandas進(jìn)行數(shù)據(jù)處理的時(shí)候藻肄,經(jīng)常會(huì)遇見(jiàn)數(shù)據(jù)類型的問(wèn)題蔑舞,當(dāng)拿到數(shù)據(jù)的時(shí)候,首先要確定拿到的是正確的數(shù)據(jù)類型嘹屯,如果數(shù)據(jù)類型不正確需要進(jìn)行數(shù)據(jù)類型的轉(zhuǎn)化攻询,再進(jìn)行數(shù)據(jù)處理。附:常見(jiàn)pandas數(shù)據(jù)類型轉(zhuǎn)化
df.describe()
- 用戶平均每筆訂單購(gòu)買2.4個(gè)商品州弟,標(biāo)準(zhǔn)差在2.3钧栖,稍稍具有波動(dòng)性。中位數(shù)在2個(gè)商品婆翔,75分位數(shù)在3個(gè)商品拯杠,說(shuō)明絕大部分訂單的購(gòu)買量都不多。最大值在99個(gè)啃奴,數(shù)字比較高潭陪。購(gòu)買金額的情況差不多,大部分訂單都集中在小額最蕾。
- 一般而言依溯,消費(fèi)類的數(shù)據(jù)分布,都是長(zhǎng)尾形態(tài)瘟则。大部分用戶都是小額黎炉,然而小部分用戶貢獻(xiàn)了收入的大頭,俗稱二八醋拧。
數(shù)據(jù)類型的轉(zhuǎn)化
df['order_dt'] = pd.to_datetime(df.order_dt,format = '%Y%m%d') #Y四位數(shù)的日期部分慷嗜,y表示兩位數(shù)的日期部分
df['month'] = df.order_dt.values.astype('datetime64[M]')
【圖】
- 時(shí)間序列的變化方式。
第一部分小結(jié):
到目前為止趁仙,我們已經(jīng)把數(shù)據(jù)類型處理成我們想要的類型了洪添。我們通過(guò)四個(gè)字段及衍生字段就可以進(jìn)行后續(xù)的分析了。
第二部分:按月數(shù)據(jù)分析
接下來(lái)我們用之前清洗好的字段進(jìn)行數(shù)據(jù)分析雀费。從用戶方向干奢、訂單方向、消費(fèi)趨勢(shì)等進(jìn)行分析盏袄。
1忿峻、消費(fèi)趨勢(shì)的分析
- 每月的消費(fèi)總金額
- 每月的消費(fèi)次數(shù)
- 每月的產(chǎn)品購(gòu)買量
- 每月的消費(fèi)人數(shù)
目的:了解這批數(shù)據(jù)的波動(dòng)形式薄啥。
01-每月消費(fèi)總金額
grouped_month = df.groupby('month')
order_month_amount = grouped_month.order_amount.sum()
order_month_amount.head()
-
用groupby創(chuàng)建一個(gè)新的對(duì)象。這里要觀察消費(fèi)總金額逛尚,需要將order_amount求和
- 按月統(tǒng)計(jì)每個(gè)月的CD消費(fèi)總金額垄惧。從圖中可以看到,前幾個(gè)月的銷量非常高漲绰寞。數(shù)據(jù)比較異常到逊。而后期的銷量則很平穩(wěn)。
02-每月的消費(fèi)次數(shù)(訂單數(shù))
grouped_month.user_id.count().plot()
- 前三個(gè)月的消費(fèi)訂單數(shù)在10000筆左右滤钱,后續(xù)月份的消費(fèi)人數(shù)則在2500人左右觉壶。
03-每月的產(chǎn)品購(gòu)買量
grouped_month.order_products.sum().plot()
- 每月的產(chǎn)品購(gòu)買量一樣呈現(xiàn)早期購(gòu)買量多,后期平穩(wěn)下降的趨勢(shì)件缸。為什么會(huì)呈現(xiàn)這個(gè)原因呢铜靶?我們假設(shè)是用戶身上出了問(wèn)題,早期時(shí)間段的用戶中有異常值他炊,第二假設(shè)是各類促銷營(yíng)銷争剿,但這里只有消費(fèi)數(shù)據(jù),所以無(wú)法判斷痊末。
04-每月的消費(fèi)人數(shù)(去重)
方法一:
df.groupby('month').user_id.apply(lambda x:len(x.drop_duplicates())).plot()
方法二:
df.groupby('month').user_id.nunique().plot() #nunique查看數(shù)據(jù)有多少不同的行
#這里會(huì)有一點(diǎn)區(qū)別蚕苇,因?yàn)橐粋€(gè)人在一個(gè)月內(nèi)可能多筆消費(fèi),可能一號(hào)買了一點(diǎn)二號(hào)買了一點(diǎn)舌胶,所以要進(jìn)行去重的操作
- 每月的消費(fèi)人數(shù)小于每月的消費(fèi)次數(shù)捆蜀,但是區(qū)別不大。前三個(gè)月每月的消費(fèi)人數(shù)在8000—10000之間幔嫂,后續(xù)月份辆它,平均消費(fèi)人數(shù)在2000不到。一樣是前期消費(fèi)人數(shù)多履恩,后期平穩(wěn)下降的趨勢(shì)锰茉。
** 附加:上面消費(fèi)趨勢(shì)的分析可以通過(guò)數(shù)據(jù)透視表分析 **
df.pivot_table(index = 'month',
values = ['order_products','order_amount','user_id'],
aggfunc = {'order_products':'sum','order_amount':'sum','user_id':'count'})
- 數(shù)據(jù)透視表是更簡(jiǎn)單的方法,有了這個(gè)之后大家用里面的數(shù)據(jù)進(jìn)行作圖也是OK的切心,而且更加的快捷飒筑,所以pandas到后面的話解決一個(gè)問(wèn)題會(huì)想到兩到三個(gè)方法。具體看那個(gè)方便绽昏,那個(gè)簡(jiǎn)單协屡。
第二部分小結(jié):
按月數(shù)據(jù)分析主要用group by簡(jiǎn)單了解了消費(fèi)趨勢(shì)
第三部分:用戶個(gè)體消費(fèi)數(shù)據(jù)分析
之前我們維度都是月,來(lái)看的是趨勢(shì)全谤。有時(shí)候我們也需要看個(gè)體來(lái)看這個(gè)人的消費(fèi)能力如何肤晓,這里劃分了五個(gè)方向如下:
- 用戶消費(fèi)金額和消費(fèi)次數(shù)的描述統(tǒng)計(jì)
- 用戶消費(fèi)金額和消費(fèi)次數(shù)的散點(diǎn)圖
- 用戶消費(fèi)金額的分布圖(二八法則)
- 用戶消費(fèi)次數(shù)的分布圖
- 用戶累計(jì)消費(fèi)金額的占比(百分之多少的用戶占了百分之多少的消費(fèi)額)
01-用戶消費(fèi)金額和消費(fèi)次數(shù)的描述統(tǒng)計(jì)
group_user = df.groupby('user_id')
group_user.sum().describe()
- 從用戶角度看,每位用戶平均購(gòu)買7張CD,最多的用戶購(gòu)買了1033張补憾。用戶的平均消費(fèi)金額(客單價(jià))100元漫萄,標(biāo)準(zhǔn)差是240,結(jié)合分位數(shù)和最大值看盈匾,平均值才和75分位接近腾务,肯定存在小部分的高額消費(fèi)用戶。
- 如果大家能夠接觸到消費(fèi)削饵、金融和錢相關(guān)的數(shù)據(jù)岩瘦,基本上都符合二八法則,小部分的用戶占了消費(fèi)的大頭
02-用戶消費(fèi)金額和消費(fèi)次數(shù)的散點(diǎn)圖
group_user.sum().query('order_amount < 4000'). plot.scatter(x = 'order_amount' , y = 'order_products')
#query后面只支持string形式的值
- 繪制用戶的散點(diǎn)圖葵孤,用戶比較健康而且規(guī)律性很強(qiáng)担钮。因?yàn)檫@是CD網(wǎng)站的銷售數(shù)據(jù),商品比較單一尤仍,金額和商品量的關(guān)系也因此呈線性,沒(méi)幾個(gè)離群點(diǎn)狭姨。
03-用戶消費(fèi)金額的分布圖(二八法則)
group_user.sum().order_amount. plot.hist(bins = 20)
#bins = 20,就是分成20塊宰啦,最高金額是14000,每個(gè)項(xiàng)就是700
- 從上圖直方圖可知饼拍,大部分用戶的消費(fèi)能力確實(shí)不高赡模,絕大部分呈現(xiàn)集中在很低的消費(fèi)檔次。高消費(fèi)用戶在圖上幾乎看不到师抄,這也確實(shí)符合消費(fèi)行為的行業(yè)規(guī)律漓柑。
- 雖然有極致干擾了我們的數(shù)據(jù),但是大部分的用戶還是集中在比較低的而消費(fèi)檔次叨吮。
04-用戶消費(fèi)次數(shù)的分布圖(二八法則)
group_user.sum().query('order_products < 100').order_products.hist(bins = 40)
- 到目前為止關(guān)于用戶的消費(fèi)行為有一個(gè)大概的了解
05-用戶累計(jì)消費(fèi)金額的占比(百分之多少的用戶占了百分之多少的消費(fèi)額)
方法一:
user_cumsum = (group_user.sum().sort_values('order_amount').cumsum)/ 2500315.63
方法二:
user_cumsum = group_user.sum().sort_values('order_amount').apply(lambda x: x.cumsum() / x.sum())
user_cumsum
#axis = 0按列計(jì)算
#cumsum滾動(dòng)累加求和
#sort_values排序辆布,升序
- 按用戶消費(fèi)金額進(jìn)行升序排序,由圖可知50%的用戶僅貢獻(xiàn)了15%的銷售額度茶鉴。而排名前5000的用戶就貢獻(xiàn)了60%的消費(fèi)額锋玲。也就是說(shuō)我們只要維護(hù)了這5000個(gè)用戶就可以把業(yè)績(jī)KPI完成60%,如果能把5000個(gè)用戶運(yùn)營(yíng)的更好就可以占比70%—80%之間涵叮。
第三部分小結(jié):
第四部分:用戶消費(fèi)行為分析
- 用戶第一次消費(fèi)(首購(gòu))惭蹂。
#在很多行業(yè)里面首購(gòu)是一個(gè)很重要的維度,它和渠道息息相關(guān)割粮,尤其是針對(duì)客單價(jià)比較高客戶留存率比價(jià)低的行業(yè)盾碗,第一次客戶從哪里來(lái)可以拓展出很多運(yùn)營(yíng)方式。
- 用戶最后一次消費(fèi)
- 新老客消費(fèi)比
- 多少用戶僅消費(fèi)了一次
- 每月新客占比
- 用戶分層
- RFM
- 新舀瓢、老廷雅、活躍、流失
- 用戶購(gòu)買周期(按訂單)
- 用戶消費(fèi)周期描述
- 用戶消費(fèi)周期分布
- 用戶生命周期(按第一次&最后一次消費(fèi))
- 用戶生命周期描述
- 用戶生命周期分布
01-用戶第一次消費(fèi)(首購(gòu))
up_user.month.min().value_counts()
- 求月份的最小值,即用戶消費(fèi)行為中的第一次消費(fèi)時(shí)間榜轿。所有用戶的第一次消費(fèi)都集中在前三個(gè)月.
02-用戶最后一次消費(fèi)
group_user.month.max().value_counts()
- 觀察用戶的最后一次消費(fèi)時(shí)間幽歼。用戶最后一次消費(fèi)比第一次消費(fèi)分布廣,大部分最后一次消費(fèi)集中在前三個(gè)月谬盐,說(shuō)明很多客戶購(gòu)買一次就不再進(jìn)行購(gòu)買甸私。隨著時(shí)間的增長(zhǎng),最后一次購(gòu)買數(shù)也在遞增飞傀,消費(fèi)呈現(xiàn)流失上升的情況皇型,用戶忠誠(chéng)度在慢慢下降。
03-新老客的消費(fèi)比
user_life = group_user.order_dt.agg(['min','max'])
user_life.head()
- user_id為1的用戶第一次消費(fèi)時(shí)間和最后一次消費(fèi)時(shí)間為19970101砸烦,說(shuō)明他只消費(fèi)了一次
用戶購(gòu)買周期
(user_life['min'] == user_life['max']).value_counts()
- -有一半的用戶只消費(fèi)了一次
04 - 用戶分層
rfm = df.pivot_table(index = 'user_id',
values = ['order_products','order_amount','order_dt'],
aggfunc = {'order_products':'max','order_amount':'sum','order_products':'sum'})
rfm.head()
#order_amount消費(fèi)總金額弃鸦,order_products消費(fèi)產(chǎn)品數(shù),order_products最近一次消費(fèi)時(shí)間
- order_products求的是消費(fèi)產(chǎn)品數(shù)幢痘,把它替換成消費(fèi)次數(shù)也是可以唬格,但是因?yàn)槲覀冞@里消費(fèi)次數(shù)是比較固定的,所以使用消費(fèi)產(chǎn)品數(shù)的維度颜说。
04-rfm距今天數(shù)
rfm['R'] =-(rfm.order_dt - rfm.order_dt.max()) / np.timedelta64(1,'D')
#-(rfm.order_dt - rfm.order_dt.max())結(jié)果為時(shí)間類型购岗,將時(shí)間格式轉(zhuǎn)化為整數(shù)或者浮點(diǎn)數(shù)的形式,可以除以單位‘D’门粪,也可以用astype轉(zhuǎn)化
rfm.rename(columns ={'order_products':'F', 'order_amount':'M'},inplace = True )
rfm.head()
#rename,重命名
- R表示客戶最近一次交易時(shí)間的間隔喊积,客戶在最近一段時(shí)間內(nèi)交易的金額。F表示客戶在最近一段時(shí)間內(nèi)交易的次數(shù),F值越大玄妈,表示客戶交易越頻繁乾吻,反之則表示客戶交易不夠活躍。M表示客戶在最近一段時(shí)間內(nèi)交易的金額拟蜻。M值越大绎签,表示客戶價(jià)值越高,反之則表示客戶價(jià)值越低瞭郑。
04-用戶分層:RFM
def rfm_func(x):
level = x.apply(lambda x :'1' if x >= 0 else '0')
label = level.R + level.F + level.M
d = {
'111':'重要價(jià)值客戶',
'011':'重要保持客戶',
'101':'重要挽留客戶',
'001':'重要發(fā)展客戶',
'110':'一般價(jià)值客戶',
'010':'一般保持客戶',
'100':'一般挽留客戶',
'000':'一般發(fā)展客戶'
}
result = d[label]
return result
rfm['label'] = rfm[['R','F','M']].apply(lambda x : x - x.mean()).apply(rfm_func,axis = 1)
rfm.head()
- 用戶分層辜御,這里使用平均數(shù)
04-用戶分層:求和
rfm.groupby('label').sum()
- M不同層次客戶的消費(fèi)累計(jì)金額,重要保持客戶的累計(jì)消費(fèi)金額最高
04-用戶分層:計(jì)數(shù)
rfm.groupby('label').count()
- 不同層次用戶的消費(fèi)人數(shù)屈张,之前重要保持客戶的累計(jì)消費(fèi)金額最高擒权,這里重要保持客戶的消費(fèi)人數(shù)排名第二,但離一般挽留用戶差距比較大阁谆,一般挽留用戶有14074人碳抄,重要保持客戶4554人
04-RFM用戶分層
rfm.loc[rfm.label == '重要價(jià)值客戶','color'] = 'g'
rfm.loc[~(rfm.label == '重要價(jià)值客戶'),'color'] = 'r'
rfm.plot.scatter('F','R',c = rfm.color)
#pandas中增加顏色需要新增加一列
- 從RFM分層可知,大部分用戶為重要保持客戶场绿,但是這是由于極致的影響剖效,所以RFM的劃分應(yīng)該盡量以業(yè)務(wù)為準(zhǔn)。盡量用小部分的用戶覆蓋大部分的額度,不要為了數(shù)據(jù)好看劃分等級(jí)璧尸。
- RFM是人工使用象限法把數(shù)據(jù)劃分為幾個(gè)立方體咒林,立方體對(duì)應(yīng)相應(yīng)的標(biāo)簽,我們可以把標(biāo)簽運(yùn)用到業(yè)務(wù)層面上爷光。比如重要保持客戶貢獻(xiàn)金額最多159203.62垫竞,我們?nèi)绾闻c業(yè)務(wù)方配合把數(shù)據(jù)提高或者維護(hù);而重要發(fā)展客戶和重要挽留客戶他們有一段時(shí)間沒(méi)有消費(fèi)了蛀序,我們?nèi)绾伟阉麄兝貋?lái)
04-用戶分層:用戶生命周期
pivoted_counts = df.pivot_table(index = 'user_id',
columns = 'month',
values = 'order_dt',
aggfunc = 'count').fillna(0)
pivoted_counts.head()
- 用戶每個(gè)月的消費(fèi)次數(shù)欢瞪,對(duì)于生命周期的劃分只需要知道用戶本月是否消費(fèi),消費(fèi)次數(shù)在這里并不重要徐裸,需要將模型進(jìn)行簡(jiǎn)化
- 使用數(shù)據(jù)透視表遣鼓,需要明確獲得什么結(jié)果。有些用戶在某月沒(méi)有進(jìn)行過(guò)消費(fèi)重贺,會(huì)用NaA表示骑祟,這里用filna填充。
04-用戶生命周期
df_purchase = pivoted_counts.applymap(lambda x : 1 if x > 0 else 0)
df_purchase.tail()
- 對(duì)于尾部數(shù)據(jù)檬姥,user_id2W+的數(shù)據(jù)是有問(wèn)題的曾我,因?yàn)閺膶?shí)際的業(yè)務(wù)場(chǎng)景上說(shuō),他們一月和二月都沒(méi)有注冊(cè)三月份才是他們第一次消費(fèi)健民。透視會(huì)把他們一月和二月的數(shù)據(jù)補(bǔ)上為0,這里面需要進(jìn)行判斷將第一次消費(fèi)作為生命周期的起始贫贝,不能從一月份開始就粗略的計(jì)算
04-用戶分層:用戶生命周期狀態(tài)變化
#此處代碼有些許問(wèn)題
def active_status(data):
status = []
for i in range(18):
#若本月沒(méi)有消費(fèi)
if data[i] == 0:
if len(status) > 0:
if status[i-1] == 'unreg':
status.append('unreg')
else:
status.append('unactive')
else:
status.append('unreg')
#若本月消費(fèi)
else:
if len(status) == 0:
status.append('new')
else:
if status[i-1] == 'unactive':
status.append('return')
elif status[i-1] == 'unreg':
status.append('new')
else:
status.append('active')
return status
pivoted_status = df_purchase.apply( active_status,axis = 1)
pivoted_status.head()
- 主要分為兩部分的判斷秉犹,以本月是否消費(fèi)為界。本月沒(méi)有消費(fèi)稚晚,還要額外判斷他是不是新客崇堵,因?yàn)椴糠钟脩羰?月份才消費(fèi)成為新客,那么在1客燕、2月份他連新客都不是鸳劳,用unreg表示。如果是老客也搓,則為unactive
- 本月若沒(méi)有消費(fèi)赏廓,需要判斷是不是第一次消費(fèi),上一個(gè)時(shí)間窗口有沒(méi)有消費(fèi)傍妒♂C可以多調(diào)試幾次理順里面的邏輯關(guān)系,對(duì)用戶進(jìn)行分層颤练。
- 《業(yè)內(nèi)主流寫法》
- 這里用戶生命周期的狀態(tài)變化是用數(shù)據(jù)透視表一次性做的既忆,但在實(shí)際業(yè)務(wù)場(chǎng)景中我們可能用SQL把它作為中間表來(lái)處理。我們有了明細(xì)表,會(huì)通過(guò)明細(xì)表來(lái)計(jì)算出狀態(tài)表患雇;也就是它的數(shù)據(jù)上個(gè)月是什么樣的情況得出來(lái)跃脊,比如上個(gè)月是新用戶或者回流用戶,我們直接用上個(gè)月的狀態(tài)left join本月的狀態(tài)苛吱。直接用SQL進(jìn)行對(duì)比
- 可以用pandas將每個(gè)月的狀態(tài)計(jì)算出來(lái)酪术,不是逐行而是月份計(jì)算,先算出一月份哪些用戶是新購(gòu)買的又谋,然后判斷二月份是否購(gòu)買拼缝,兩者left join
每月不同活躍用戶的計(jì)數(shù)
purchase_status_ct = pivoted_status.replace('unreg',np.NaN).apply(lambda x : pd.value_counts(x))
purchase_status_ct
- 由上表可知彰亥,每月用戶的消費(fèi)狀態(tài)變化咧七。活躍用戶任斋、持續(xù)消費(fèi)的用戶對(duì)應(yīng)的是消費(fèi)運(yùn)營(yíng)質(zhì)量继阻。回流用戶废酷,之前不消費(fèi)本月才消費(fèi)對(duì)應(yīng)的是喚回運(yùn)營(yíng)瘟檩。不活躍的用戶對(duì)應(yīng)的是流失
- 這里可以針對(duì)業(yè)務(wù)模型下個(gè)定義:流失用戶增加,回流用戶正在減少
05-用戶購(gòu)買周期(按訂單)
order_diff = group_user.apply(lambda x : x.order_dt - x.order_dt.shift())
order_diff.head(10)
#將用戶分組后澈蟆,每個(gè)用戶的訂單購(gòu)買時(shí)間進(jìn)行錯(cuò)位相減
- user_id 1為空值墨辛,表示該客戶只購(gòu)買過(guò)一個(gè)訂單。user_id為2 的用戶第二筆訂單與第二筆訂單在同一天購(gòu)買
05-用戶消費(fèi)周期分布
(order_diff / np.timedelta64(1,'D')).hist(bins = 20)
- 訂單周期呈指數(shù)分布趴俘,用戶的平均購(gòu)買周期是68天睹簇,絕大部分用戶的購(gòu)買周期都低于100天擎椰。
06-用戶生命周期(第一筆訂單時(shí)間 & 最后一筆訂單時(shí)間)
(user_life['max'] - user_life['min']).describe()
- 數(shù)據(jù)偏移比較大朗若,中位數(shù)是0天也就是超過(guò)50%的用戶他的生命周期是0天只購(gòu)買了一次,但是平均生命周期有134天级遭,最大值是544天
06-用戶生命周期(第一筆訂單時(shí)間 & 最后一筆訂單時(shí)間)
((user_life['max'] - user_life['min'])/np.timedelta64(1,'D')).hist(bins = 40)
- 用戶的生命周期受只購(gòu)買一次的用戶影響比較厲害(可以排除)疲憋,用戶均消費(fèi)134天凿渊,中位數(shù)僅0天
06-用戶生命周期大于0天分布圖
u_l = (user_life['max'] - user_life['min'])/np.timedelta64(1,'D')
u_l[u_l > 0].hist(bins = 40)
- 篩選出lifetime>0,既排除了僅消費(fèi)了一次那些人,有不少用戶生命周期靠攏在0天缚柳,部分質(zhì)量差的用戶雖然消費(fèi)了兩次埃脏,但是任然無(wú)法持續(xù),在用戶首次消費(fèi)30天內(nèi)應(yīng)該盡量引導(dǎo)喂击。少部分用戶集中在50—300天剂癌,屬于普通型的生命周期。高質(zhì)量用戶的生命周期翰绊,集中在400天以后佩谷,這屬于忠誠(chéng)用戶旁壮。
07-復(fù)購(gòu)率和回購(gòu)率的分析
#復(fù)購(gòu)率:自然月內(nèi),購(gòu)買多次的用戶占比
#回購(gòu)率:曾經(jīng)購(gòu)買過(guò)的用戶咋某一時(shí)期內(nèi)的再次購(gòu)買占比
07-回購(gòu)率
purchase_r = pivoted_counts.applymap(lambda x : 1 if x > 1 else np.NaN if x == 0 else 0)
purchase_r.head()
- applymap針對(duì)DataFrame里的所有數(shù)據(jù)谐檀。用lambda進(jìn)行判斷抡谐,因?yàn)檫@里設(shè)計(jì)了多個(gè)結(jié)果,所以要兩個(gè)if else
07-回購(gòu)率
(purchase_r.sum() / purchase_r.count()).plot(figsize = (10,4))
- 用sum和count相除即可計(jì)算出復(fù)購(gòu)率桐猬。因?yàn)檫@兩個(gè)函數(shù)都會(huì)忽略NAN麦撵,而NAN是沒(méi)有消費(fèi)的用戶,count不論是0還是1都會(huì)統(tǒng)計(jì)溃肪,所以是總的消費(fèi)用戶數(shù)免胃,而sum求何計(jì)算了兩次以上的消費(fèi)用戶。這里用了比較巧妙的替代法計(jì)算復(fù)購(gòu)率惫撰,SQL中也可以用羔沙。
- 圖上可以看出復(fù)購(gòu)率在早期,因?yàn)榇罅啃掠脩艏尤氲年P(guān)系厨钻,新客的復(fù)購(gòu)率并不高扼雏,譬如1月新客們的復(fù)購(gòu)率只有6%左右。而在后期夯膀,這時(shí)的用戶都是大浪淘沙剩下的老客戶诗充,復(fù)購(gòu)率比較穩(wěn)定,在20%左右.
單看新客和老客诱建,復(fù)購(gòu)率有三倍左右的差距 - 接下來(lái)計(jì)算回購(gòu)率蝴蜓。回購(gòu)率是某一個(gè)時(shí)間窗口內(nèi)消費(fèi)的用戶俺猿,在下一個(gè)時(shí)間窗口人就消費(fèi)的占比励翼。我1月消費(fèi)用戶1000,他們中有300個(gè)2月依然消費(fèi)辜荠,回購(gòu)率是30%
07-回購(gòu)率
#和前面用戶生命周期是相關(guān)的
消費(fèi)金額進(jìn)行數(shù)據(jù)透視
pivoted_amount = df.pivot_table(index = 'user_id',columns = 'month',values = 'order_amount',aggfunc = 'mean').fillna(0)
columns_month = df.month.sort_values().astype('str').unique()
pivoted_amount.columns = columns_month
pivoted_amount.head()
- 消費(fèi)變量,1代表這個(gè)月消費(fèi)過(guò)抓狭,0代表沒(méi)有消費(fèi)過(guò)
07-回購(gòu)率
def purchase_return(data):
status = []
for i in range(17):
if data[i] == 1:
if data[i+1] ==1:
status.append(1)
if data[i+1] == 0:
status.append(0)
else:
status.append(np.NaN)
status.append(np.NaN)
return status
pivoted_purchase_return = pivoted_purchase.apply(purchase_return,axis = 1)
pivoted_purchase_return.head(5)
- 0代表當(dāng)月消費(fèi)過(guò)次月沒(méi)有消費(fèi)過(guò)伯病,1代表當(dāng)月消費(fèi)過(guò)次月依然消費(fèi)
- 新建一個(gè)判斷函數(shù)。data是輸入數(shù)據(jù)否过,既用戶在18個(gè)月內(nèi)是否消費(fèi)的記錄午笛,status是空列表,后續(xù)用來(lái)保存用戶是否回購(gòu)的字段苗桂。因?yàn)橛?8個(gè)月药磺,所以每個(gè)月都要進(jìn)行一次判斷,需要用到循環(huán)煤伟。if的主要邏輯是癌佩,如果用戶本月進(jìn)行過(guò)消費(fèi)木缝,且下月消費(fèi)過(guò),記為1围辙,沒(méi)有消費(fèi)過(guò)是0.本月若沒(méi)有進(jìn)行過(guò)消費(fèi)我碟,為NAN,后續(xù)的統(tǒng)計(jì)中進(jìn)行排除姚建。apply函數(shù)應(yīng)用在所有行上矫俺,獲得想要的結(jié)果。
- 最后計(jì)算和復(fù)購(gòu)率大同小異掸冤,用count和sum求出厘托,從圖中可以看出,用戶的回購(gòu)率高于復(fù)購(gòu),約在30%左右稿湿,和老客戶差異不大铅匹。從回購(gòu)率和復(fù)購(gòu)率綜合分析可以得出,新客的整體質(zhì)量低于老客缎罢,老客的忠誠(chéng)度(回購(gòu)率)表現(xiàn)較好伊群,消費(fèi)頻次稍次,這是CDNow網(wǎng)站的用戶消費(fèi)特征策精。