目錄
一.項(xiàng)目背景與數(shù)據(jù)來(lái)源
二河爹、提出問(wèn)題
三. 數(shù)據(jù)處理
3.1 導(dǎo)入數(shù)據(jù)
--3.1.1 導(dǎo)入常用的庫(kù)
--3.1.2 導(dǎo)入源數(shù)據(jù)
--3.1.3 查看數(shù)據(jù)的基本信息
3.2 描述性統(tǒng)計(jì)
3.3 數(shù)據(jù)處理
--3.3.1 缺省值
--3.3.2 數(shù)據(jù)清洗
四. 用戶總體消費(fèi)趨勢(shì)分析
每月的總銷售額乍丈、每月的消費(fèi)次數(shù)、每月的銷量阳柔、每月的消費(fèi)人數(shù)波動(dòng)
五.用戶個(gè)體消費(fèi)數(shù)據(jù)分析
5.1 用戶消費(fèi)金額和消費(fèi)次數(shù)的描述統(tǒng)計(jì)
5.2 用戶消費(fèi)金額和消費(fèi)次數(shù)的散點(diǎn)圖
5.3 用戶消費(fèi)金額的分布圖(二八法則)
5.4 用戶消費(fèi)次數(shù)的分布圖(二八法則)
六.用戶消費(fèi)周期分析
6.1 用戶購(gòu)買周期(按訂單)
--6.1.1 用戶消費(fèi)周期描述
--6.1.2 用戶消費(fèi)周期分布
6.2 用戶生命周期(按第一次&最后一次消費(fèi))
-- 6.2.1 用戶生命周期描述
--6.2.2 用戶生命周期分布
七.用戶分層
7.1 按用戶價(jià)值分層---RFM模型
7.2 按用戶活躍程度分層---新用戶、活躍用戶蚓峦、不活躍用戶舌剂、回流用戶
八.用戶質(zhì)量分析
8.1 多少用戶僅消費(fèi)一次?
8.2 復(fù)購(gòu)率
8.3 回購(gòu)率
8.4 分析留存率(3,7,15,30,90,365天為周期)
8.5 大客戶的貢獻(xiàn)率
--8.5.1 用戶銷售額貢獻(xiàn)情況
--8.5.2 用戶銷量貢獻(xiàn)情況
九.結(jié)論
一暑椰、項(xiàng)目背景
CDNow曾經(jīng)是一家在線音樂(lè)零售平臺(tái)霍转,后被德國(guó)波泰爾斯曼娛樂(lè)集團(tuán)公司出資收購(gòu),其資產(chǎn)總價(jià)值在最輝煌時(shí)曾超過(guò)10億美元一汽。本文主要通過(guò)分析CDNow網(wǎng)站的用戶購(gòu)買明細(xì)來(lái)分析該網(wǎng)站的用戶消費(fèi)行為避消,使運(yùn)營(yíng)部門在營(yíng)銷時(shí)更加具有針對(duì)性,從而節(jié)省成本召夹,提升效率岩喷。
數(shù)據(jù)來(lái)源
本次分析數(shù)據(jù)來(lái)源CDNow網(wǎng)站的用戶在1997年1月1日至1998年6月30日期間內(nèi)購(gòu)買CD交易明細(xì)。
數(shù)據(jù)下載地址——提取碼: va7h
數(shù)據(jù)集一共有用戶ID监憎,購(gòu)買日期纱意,訂單數(shù),訂單金額四個(gè)字段鲸阔。
二偷霉、提出問(wèn)題
對(duì)用戶進(jìn)行消費(fèi)特征分析。分析框架如下:
三.數(shù)據(jù)處理
3.1 導(dǎo)入數(shù)據(jù)
3.1.1 導(dǎo)入常用的庫(kù):
#導(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)格
3.1.2 導(dǎo)入源數(shù)據(jù)
數(shù)據(jù)中未包含列標(biāo)題,因此在導(dǎo)入數(shù)據(jù)時(shí)要設(shè)置列標(biāo)題。分隔符為空格妓忍。
#導(dǎo)入源數(shù)據(jù)
columns = ['用戶ID','購(gòu)買日期','訂單數(shù)','訂單金額']
df = pd.read_table("CDNOW_master.txt",names = columns,sep = '\s+')
- 加載包和數(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)行分隔
- 消費(fèi)行業(yè)或者是電商行業(yè)一般是通過(guò)訂單數(shù)惠况,訂單額,購(gòu)買日期宁仔,用戶ID這四個(gè)字段來(lái)分析的稠屠。基本上這四個(gè)字段就可以進(jìn)行很豐富的分析翎苫。
3.1.3 查看數(shù)據(jù)的基本信息
#默認(rèn)輸出前五行
df.head()
- 觀察數(shù)據(jù)权埠,購(gòu)買日期列表示時(shí)間,但現(xiàn)在它只是年月日組合的一串?dāng)?shù)字煎谍,數(shù)據(jù)不是時(shí)間類型攘蔽,沒(méi)有時(shí)間含義,需要轉(zhuǎn)換粱快。購(gòu)買金額是小數(shù)秩彤。
- 數(shù)據(jù)中存在一個(gè)用戶在同一天或不同天下多次訂單的情況,如用戶ID為2的用戶就在1月12日買了兩次事哭。
3.2 描述性統(tǒng)計(jì)
#數(shù)值列的匯總統(tǒng)計(jì)信息
df.describe()
describe是描述統(tǒng)計(jì),對(duì)用戶數(shù)據(jù)特征進(jìn)行整體性判斷:
- 從數(shù)據(jù)的統(tǒng)計(jì)描述信息中可以看出瓜富,用戶每個(gè)訂單平均購(gòu)買2.41個(gè)商品鳍咱,每個(gè)訂單平均消費(fèi)35.89元。
- 購(gòu)買商品數(shù)量的標(biāo)準(zhǔn)差為2.33与柑,說(shuō)明數(shù)據(jù)具有一定的波動(dòng)性谤辜;中位數(shù)為2個(gè)商品,75分位數(shù)為3個(gè)商品,說(shuō)明大部分訂單的購(gòu)買數(shù)量都不多价捧。最大值在99個(gè)丑念,數(shù)字比較高。購(gòu)買金額的情況差不多结蟋,大部分訂單都集中在小額脯倚。
- 一般而言,消費(fèi)類的數(shù)據(jù)分布,都是長(zhǎng)尾形態(tài)推正。大部分用戶都是小額恍涂,然而小部分用戶貢獻(xiàn)了收入的大頭,俗稱二八植榕。
3.3 數(shù)據(jù)處理
3.3.1 缺省值
#索引再沧,數(shù)據(jù)類型和內(nèi)存信息
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)化
3.3.2 數(shù)據(jù)清洗
將時(shí)間進(jìn)行數(shù)據(jù)類型轉(zhuǎn)換技俐,并增加月度列。
# 將購(gòu)買日期列進(jìn)行數(shù)據(jù)類型轉(zhuǎn)換
df['購(gòu)買日期'] = pd.to_datetime(df.購(gòu)買日期,format = '%Y%m%d') #Y四位數(shù)的日期部分统台,y表示兩位數(shù)的日期部分
df['月份'] = df.購(gòu)買日期.values.astype('datetime64[M]')
df.head()
- pd.to_datetime可以將特定的字符串或者數(shù)字轉(zhuǎn)換成時(shí)間格式雕擂,其中的format參數(shù)用于匹配。例如19970101贱勃,%Y匹配前四位數(shù)字1997井赌,如果y小寫只匹配兩位數(shù)字97,%m匹配01贵扰,%d匹配01仇穗。
- 另外,小時(shí)是%h戚绕,分鐘是%M纹坐,注意和月的大小寫不一致,秒是%s舞丛。若是1997-01-01這形式耘子,則是%Y-%m-%d,以此類推球切。
-
astype也可以將時(shí)間格式進(jìn)行轉(zhuǎn)換谷誓,比如[M]轉(zhuǎn)化成月份。我們將月份作為消費(fèi)行為的主要事件窗口吨凑,選擇哪種時(shí)間窗口取決于消費(fèi)頻率捍歪。
檢查有無(wú)空值
df.info()
四.用戶總體消費(fèi)趨勢(shì)分析
#解決中文顯示參數(shù)設(shè)置
plt.rcParams['font.sans-serif']=['SimHei'] #用來(lái)正常顯示中文標(biāo)簽
plt.rcParams['axes.unicode_minus'] = False #用來(lái)正常顯示負(fù)號(hào)
# 設(shè)置圖的大小,添加子圖
plt.figure(figsize=(20,15))
# 每月的總銷售額
plt.subplot(221)
df.groupby('月份')['訂單金額'].sum().plot(fontsize=24)
plt.title('總銷售額',fontsize=24)
#每月的消費(fèi)次數(shù)
plt.subplot(222)
df.groupby('月份')['購(gòu)買日期'].count().plot(fontsize=24)
plt.title('消費(fèi)次數(shù)',fontsize=24)
#每月的銷量
plt.subplot(223)
df.groupby('月份')['訂單數(shù)'].sum().plot(fontsize=24)
plt.title('總銷量',fontsize=24)
#每月的消費(fèi)人數(shù)
plt.subplot(224)
df.groupby('月份')['用戶ID'].apply(lambda x:len(x.unique())).plot(fontsize=24)
plt.title('消費(fèi)人數(shù)',fontsize=24)
plt.tight_layout() # 設(shè)置子圖的間距
plt.show()
- 四個(gè)折線圖的整體趨勢(shì)基本一致,可以看出來(lái)费封,1997年前3個(gè)月的銷量特別高焕妙,隨之而來(lái)的銷售額也是暴漲,在3月份之后驟然下降弓摘,接近平穩(wěn)焚鹊。
- 為什么會(huì)呈現(xiàn)這個(gè)原因呢?我們假設(shè)是用戶身上出了問(wèn)題韧献,早期時(shí)間段的用戶中有異常值末患,第二假設(shè)是各類促銷營(yíng)銷,但這里只有消費(fèi)數(shù)據(jù)锤窑,所以無(wú)法判斷璧针。
另一方面,在2月到3月這段期間渊啰,可以發(fā)現(xiàn)消費(fèi)人數(shù)稍有下降探橱,但總銷量與總銷售額卻依然上升,是不是說(shuō)明3月份的用戶中有我們需要重點(diǎn)發(fā)展的高價(jià)值客戶呢绘证? - Python繪圖如何顯示中文標(biāo)題
五. 用戶個(gè)體消費(fèi)數(shù)據(jù)分析
之前我們維度是用戶整體隧膏,看的是趨勢(shì)。有時(shí)候我們也需要看個(gè)體來(lái)看這個(gè)人的消費(fèi)能力如何嚷那,這里劃分了五個(gè)方向如下:
5.1 用戶消費(fèi)金額胞枕,消費(fèi)次數(shù)的描述統(tǒng)計(jì)
# 根據(jù)用戶id進(jìn)行分組
group_user = df.groupby('用戶ID').sum()
group_user.describe()
- 從用戶角度看,每位用戶平均購(gòu)買7張CD魏宽,最多的用戶購(gòu)買了1033張腐泻。用戶的平均消費(fèi)金額(客單價(jià))100元,標(biāo)準(zhǔn)差是240队询,結(jié)合分位數(shù)和最大值看派桩,平均值才和75分位接近,肯定存在小部分的高額消費(fèi)用戶,這也符合二八法則娘摔。
5.2 用戶消費(fèi)金額和消費(fèi)次數(shù)的散點(diǎn)圖
#查詢條件:訂單金額 < 4000
group_user.query('訂單金額 < 4000').plot.scatter(x='訂單金額',y='訂單數(shù)')
- 繪制用戶的散點(diǎn)圖窄坦,用戶比較健康而且規(guī)律性很強(qiáng)。因?yàn)檫@是CD網(wǎng)站的銷售數(shù)據(jù)凳寺,商品比較單一,金額和商品量的關(guān)系也因此呈線性彤侍,沒(méi)幾個(gè)離群點(diǎn)肠缨。
5.3 用戶消費(fèi)金額的分布圖(二八法則)
group_user.訂單金額. plot.hist(bins = 20)
#bins = 20,就是分成20塊,最高金額是14000盏阶,每個(gè)項(xiàng)就是700
從圖上看出晒奕,用戶的消費(fèi)呈集中趨勢(shì),可能是有個(gè)別的極大值干擾導(dǎo)致。
可以排除極大值再看看分布情況
group_user.query("訂單金額< 800")['訂單金額'].plot.hist(bins=20)
篩選出了消費(fèi)金額小于800的用戶脑慧,我們可以看到:
- 大部分用戶的消費(fèi)能力并不高魄眉,將近半數(shù)的用戶消費(fèi)金額不超過(guò)40元,高消費(fèi)用戶( >200元 )不超過(guò)2000人闷袒。
- 從上圖直方圖可知坑律,大部分用戶的消費(fèi)能力確實(shí)不高,絕大部分呈現(xiàn)集中在很低的消費(fèi)檔次囊骤。高消費(fèi)用戶在圖上幾乎看不到晃择,這也確實(shí)符合消費(fèi)行為的行業(yè)規(guī)律。
- 雖然有極端數(shù)據(jù)干擾也物,但是大部分的用戶還是集中在比較低的消費(fèi)檔次宫屠。
5.4 用戶消費(fèi)次數(shù)的分布圖(二八法則)
group_user.query('訂單數(shù) < 100').訂單數(shù).hist(bins = 40)
- 大部分用戶購(gòu)買CD的數(shù)量都是在3張以內(nèi),購(gòu)買大量CD的用戶數(shù)量并不多滑蚯。
六.用戶消費(fèi)周期分析
6.1 用戶購(gòu)買周期(按訂單)
6.1.1 用戶消費(fèi)周期描述
#每個(gè)用戶的每次購(gòu)買時(shí)間間隔
order_diff = df.groupby('用戶ID').apply(lambda x:x['購(gòu)買日期'] - x['購(gòu)買日期'].shift())
order_diff.head(10)
這是每個(gè)用戶的每次購(gòu)買時(shí)間間隔浪蹂。
order_diff.describe()
- 平均每個(gè)用戶的購(gòu)買時(shí)間間隔是68天,間隔最長(zhǎng)的是533天告材。想要召回用戶坤次,在60天左右的消費(fèi)間隔是比較好的。
- 絕大部分用戶的消費(fèi)周期都低于100天创葡。
6.1.2 用戶消費(fèi)周期分布
plt.figure(figsize=(15,5))
plt.hist((order_diff / np.timedelta64(1, 'D')).dropna(), bins = 50)
plt.xlabel('消費(fèi)周期',fontsize=24)
plt.ylabel('頻數(shù)',fontsize=24)
plt.title('用戶消費(fèi)周期分布圖',fontsize=24);
- 典型的(指數(shù))長(zhǎng)尾分布浙踢,大部分用戶的消費(fèi)間隔確實(shí)比較短。不妨將時(shí)間召回點(diǎn)設(shè)為消費(fèi)后立即贈(zèng)送優(yōu)惠券灿渴,消費(fèi)后10天詢問(wèn)用戶禮品怎么樣洛波,消費(fèi)后20天提醒優(yōu)惠券到期,消費(fèi)后30天短信推送骚露。
6.2 用戶生命周期(按第一次&最后一次消費(fèi))
6.2.1 用戶生命周期描述
接下來(lái)計(jì)算每一位用戶生命周期蹬挤,這里定義第一次消費(fèi)至最后一次消費(fèi)為整個(gè)用戶生命。
orderdt_min=df.groupby('用戶ID').購(gòu)買日期.min()#第一次消費(fèi)
orderdt_max=df.groupby('用戶ID').購(gòu)買日期.max()#最后一次消費(fèi)
(orderdt_max-orderdt_min).head()
計(jì)算用戶的平均生命周期棘幸。
(orderdt_max-orderdt_min).mean()
- 所有用戶的平均生命周期是134天焰扳,比預(yù)想的高,但是平均數(shù)不具有代表性误续,接下來(lái)還是看一下分布情況吨悍。
6.2.2 用戶生命周期分布
((orderdt_max-orderdt_min)/np.timedelta64(1,'D')).hist(bins=15)
#因?yàn)閿?shù)據(jù)類型是timedelta時(shí)間,無(wú)法直接作出直方圖蹋嵌,所以先換算成數(shù)值育瓜。換算的方式直接除timedelta函數(shù)即可,np.timedelta64(1, ‘D’)栽烂,D表示天躏仇,1表示1天恋脚,作為單位使用的。因?yàn)閙ax-min已經(jīng)表示為天了焰手,兩者相除就是周期
- 大部分用戶只消費(fèi)了一次糟描,所有生命周期的大頭都集中在了0天。
但這不是我們想要的答案书妻,不妨將只消費(fèi)了一次的新客排除船响,來(lái)計(jì)算所有消費(fèi)過(guò)兩次以上的老客的生命周期。
#計(jì)算所有消費(fèi)過(guò)兩次以上的老客的生命周期
life_time = (orderdt_max - orderdt_min).reset_index()
life_time.head()
轉(zhuǎn)換成DataFrame
#用戶生命周期分布圖
plt.figure(figsize=(10,5))
life_time['life_time'] = life_time.購(gòu)買日期 / np.timedelta64(1,'D')
life_time[life_time.life_time > 0].life_time.hist(bins = 100, figsize = (12,6))
- 上圖可見(jiàn)驻子,用戶生命周期呈現(xiàn)雙峰趨勢(shì)灿意,20天內(nèi)生命周期的用戶是一個(gè)高峰礼饱,400至500天內(nèi)生命周期的用戶是另一個(gè)高峰友存。
- 根據(jù)此情況,應(yīng)該在20天內(nèi)對(duì)客戶進(jìn)行引導(dǎo)缎除,促進(jìn)其再次消費(fèi)并形成消費(fèi)習(xí)慣域慷,延長(zhǎng)其生命周期荒辕;在100至400天的用戶,也要根據(jù)其特點(diǎn)推出有針對(duì)性的營(yíng)銷活動(dòng)犹褒,引導(dǎo)其持續(xù)消費(fèi)抵窒。
分析去掉0天生命周期的用戶之后的用戶生命周期的平均值。
#去掉0天生命周期的用戶之后的用戶生命周期的平均值
life_time[life_time.life_time>0].購(gòu)買日期.mean()
- 可見(jiàn)叠骑,若在用戶首次消費(fèi)后李皇,加強(qiáng)對(duì)其再次消費(fèi)的引導(dǎo),可將其生命周期延長(zhǎng)至原來(lái)的兩倍宙枷。
七.用戶分層
7.1 按用戶價(jià)值分層---RFM模型
為了進(jìn)行精細(xì)化運(yùn)營(yíng)掉房,可以利用RMF模型對(duì)用戶價(jià)值指數(shù)(衡量歷史到當(dāng)前用戶貢獻(xiàn)的收益)進(jìn)行計(jì)算,其中
最近一次消費(fèi)-R:客戶最近一次交易時(shí)間的間隔慰丛。R值越大卓囚,表示客戶交易發(fā)生的日期越久,反之則交易發(fā)生的日期越近诅病。
消費(fèi)頻率-F:客戶在最近一段時(shí)間內(nèi)交易的次數(shù)哪亿。F值越大,表示客戶交易越頻繁贤笆,反之則表示客戶交易不夠活躍蝇棉。
消費(fèi)金額-M:客戶在最近一段時(shí)間內(nèi)交易的金額。M值越大芥永,表示客戶價(jià)值越高银萍,反之則表示客戶價(jià)值越低。
根據(jù)上述三個(gè)維度恤左,對(duì)客戶做細(xì)分
rfm = df.pivot_table(index = '用戶ID',
values = ['訂單金額','購(gòu)買日期','訂單數(shù)'],
aggfunc = {'訂單金額':'sum',
'購(gòu)買日期':'max',
'訂單數(shù)':'sum'})
rfm.head()
# 日期的最大值與當(dāng)前日期的差值為R
rfm['R'] = (rfm['購(gòu)買日期'].max() - rfm['購(gòu)買日期']) / np.timedelta64(1,'D')
rfm.rename(columns = {'訂單金額':'M',
'訂單數(shù)':'F'},
inplace=True)
# 構(gòu)建rfm模型公式
def get_rfm(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()) / x.std()).apply(get_rfm,axis=1)
rfm.head()
#求和
rfm.groupby('label').sum()
- M列中不同層次客戶的消費(fèi)累計(jì)金額贴唇,重要保持客戶的累計(jì)消費(fèi)金額為159203.62,排名最高
rfm.groupby('label').size()
- 以上為不同層次用戶的消費(fèi)人數(shù)飞袋,一般挽留用戶的消費(fèi)人數(shù)排名第一戳气,有14074人,重要保持客戶排名第二巧鸭,有4554人瓶您,與一般挽留用戶差距比較大,但累計(jì)消費(fèi)金額最多纲仍,業(yè)務(wù)方可以根據(jù)結(jié)果對(duì)客戶分類運(yùn)營(yíng)呀袱,降低營(yíng)銷成本,提高ROI郑叠。
7.2 按用戶活躍程度分層---新用戶夜赵、活躍用戶、不活躍用戶乡革、回流用戶
- 新用戶的定義是第一次消費(fèi)寇僧。
- 活躍用戶即老客,在某一個(gè)時(shí)間窗口內(nèi)有過(guò)消費(fèi)沸版。
- 不活躍用戶則是時(shí)間窗口內(nèi)沒(méi)有消費(fèi)過(guò)的老客嘁傀。
- 回流用戶是在上一個(gè)窗口中沒(méi)有消費(fèi),而在當(dāng)前時(shí)間窗口內(nèi)有過(guò)消費(fèi)视粮。
#將用戶消費(fèi)數(shù)據(jù)進(jìn)行數(shù)據(jù)透視:
#用戶活躍程度分層
#將用戶消費(fèi)數(shù)據(jù)進(jìn)行數(shù)據(jù)透視:
df1 = df.pivot_table(index = "用戶ID",
columns = "月份",
values = '購(gòu)買日期',
aggfunc = 'count').fillna(0)
df1.head()
- 圖中的數(shù)字(0细办,1,2)代表了當(dāng)月的消費(fèi)次數(shù)蕾殴。
df2 = df1.applymap(lambda x:1 if x>0 else 0)
df2.tail()
- 0代表當(dāng)月沒(méi)有消費(fèi)笑撞,1代表有消費(fèi)。
def active_status(data):
status=[]
for i in range(18): #共18個(gè)月
#若本月沒(méi)有消費(fèi)
if data[i]==0:
if len(status)>0:#前面某月消費(fèi)過(guò)区宇,是老客
if status[i-1]=='unreg':#前一個(gè)月不是首次消費(fèi)娃殖,不是新客
status.append('unreg')#則本月也不是新客
else:
status.append('unactive')#前一個(gè)月是首次消費(fèi),屬于新客议谷,則本月為不活躍用戶
else:
status.append('unreg')#前面某月沒(méi)有消費(fèi)過(guò)炉爆,則本月也不是新客
#若本月消費(fèi)
else:
if len(status)==0:#前面沒(méi)有消費(fèi)過(guò)
status.append('new')#則為新客
else:#前面消費(fèi)過(guò)
if status[i-1] =='unactive':#前一個(gè)月沒(méi)有消費(fèi),是不活躍用戶
status.append('return')#本月為回流用戶
elif status[i-1]=='unreg':#前一個(gè)月沒(méi)有消費(fèi)卧晓,不是新客
status.append('new')
else:#前一個(gè)月是首次消費(fèi)
status.append('active')#本月為活躍用戶
return status
#可得到一張不同用戶在不同月份的不同狀態(tài)(new=新芬首、active=活躍、return=回流逼裆、unactive=流失),unreg相當(dāng)于未注冊(cè)郁稍,指這個(gè)用戶在這個(gè)月及以前從未購(gòu)買過(guò)產(chǎn)品,主要為了統(tǒng)計(jì)起來(lái)更加方便而加進(jìn)去胜宇。
indexs=df['月份'].sort_values().astype('str').unique()
df3=df2.apply(lambda x:pd.Series(active_status(x),index=indexs),axis=1)
df3.head()
#把unreg替換成NaN耀怜,再用fillna(0)把空值填為0恢着。然后轉(zhuǎn)置,把月份作為索引行财破,狀態(tài)作為列掰派,得到如下的表
df4=df3.replace('unreg',np.NaN).apply(lambda x:pd.value_counts(x)).fillna(0).T
df4
- 從表中可以看出,新客都是集中在前三個(gè)月左痢,回流用戶整體在1000左右靡羡,而不活躍用戶數(shù)量隨時(shí)間稍有上升。
#作出非堆積效果圖:
u =df4.reset_index()
labels = u[['active','new','return','unactive']].columns
plt.figure(figsize=(15,5))
plt.stackplot(u['index'].astype(str).apply(lambda x:x[:-3]), u['active'],u['new'],u['return'],u['unactive'], labels=labels)
plt.xlabel('月份')
plt.ylabel('消費(fèi)人數(shù)')
plt.title('每月的消費(fèi)人數(shù)')
plt.legend(loc = 'upper left');
df5=df4.apply(lambda x:x/x.sum(),axis=1)#每一層用戶占總用戶的比例
df5
由上表可知俊性,每月的用戶消費(fèi)狀態(tài)變化:
- 新客用戶:僅在前三個(gè)月略步,后續(xù)再無(wú)新增客戶。
- 活躍用戶:比例持續(xù)下降定页,說(shuō)明持續(xù)消費(fèi)的用戶數(shù)量在減少趟薄,也說(shuō)明運(yùn)營(yíng)部門的促活效果并不好。
- 回流用戶:比例也稍有下降拯勉,在4%左右波動(dòng)竟趾。
- 不活躍用戶:比例稍有上升,流失較大宫峦。
八.用戶質(zhì)量分析
8.1 多少用戶僅消費(fèi)了一次岔帽? (一天內(nèi)消費(fèi)多次記作一次)
a = df.groupby('用戶ID')['購(gòu)買日期'].agg(['min','max']).reset_index()
new_old = (a['min'] == a['max']).value_counts().values
plt.pie(x = new_old,
autopct = '%.1f%%',
shadow = True,
explode = [0.08,0],
textprops = {'fontsize' : 11})
plt.axis('equal')
plt.legend(['僅消費(fèi)一次','多次消費(fèi)'])
- 有超過(guò)一半的用戶僅消費(fèi)了一次,這也說(shuō)明了運(yùn)營(yíng)不利导绷,留存效果不好犀勒。
8.2 復(fù)購(gòu)率
復(fù)購(gòu)率的定義:在某時(shí)間窗口內(nèi)消費(fèi)兩次及以上的用戶在總消費(fèi)用戶中占比。這里的時(shí)間窗口是月妥曲,如果一個(gè)用戶在同一天下了兩筆訂單贾费,這里也將他算作復(fù)購(gòu)用戶
#每個(gè)用戶在每月的訂單數(shù)
pivoted_df=df.pivot_table(index='用戶ID',columns='月份',values='購(gòu)買日期',#pivot_table透視表
aggfunc='count').fillna(0)#某些用戶在某月沒(méi)有消費(fèi)過(guò),用nan表示檐盟,這里用0填充
pivoted_df.head()
#轉(zhuǎn)換:消費(fèi)2次以上記為1褂萧,消費(fèi)1次記為0,消費(fèi)0次記為NAN
#applymap針對(duì)dataframe所有數(shù)據(jù)
pivoted_df_transf=pivoted_df.applymap(lambda x: 1 if x>1 else np.nan if x==0 else 0)
pivoted_df_transf.head()
#count統(tǒng)計(jì)所有非空數(shù)據(jù)個(gè)數(shù)表示總消費(fèi)用戶數(shù)葵萎,sum計(jì)算非0數(shù)據(jù)的和表示消費(fèi)兩次以上的用戶數(shù)
df_duplicate =pd.DataFrame(pivoted_df_transf.sum()/pivoted_df_transf.count()).reset_index()
df_duplicate.columns = ['Date', 'DuplicatedRate']
df_duplicate['Date'] = df_duplicate.Date.astype(str).apply(lambda x:x[:-3])
plt.figure(figsize = (15,6))
plt.plot(df_duplicate.Date, df_duplicate.DuplicatedRate)
plt.xlabel('時(shí)間', fontsize=24)
plt.ylabel('復(fù)購(gòu)率',fontsize=24)
# plt.ylim(0,1)
plt.title('復(fù)購(gòu)率的變化',fontsize=24)
- 說(shuō)明:圖上可以看出復(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)率有三倍左右的差距滨嘱。
8.3 回購(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%躺彬。
#回購(gòu)率
#每個(gè)用戶每個(gè)月平均消費(fèi)金額
pivoted_money=df.pivot_table(index='用戶ID',columns='月份',values='訂單金額',
aggfunc='mean').fillna(0)
columns_month=df.月份.sort_values().astype('str').unique()
pivoted_money.columns=columns_month
pivoted_money.head()
#將有消費(fèi)的記為1,沒(méi)有消費(fèi)的記為0
pivoted_purchase=pivoted_money.applymap(lambda x:1 if x>0 else 0)
pivoted_purchase.head()
#如果本月進(jìn)行消費(fèi)梅惯,下月也進(jìn)行消費(fèi)宪拥,則記為1;如果下月沒(méi)有消費(fèi)铣减,則記為0她君,若本月沒(méi)有記為消費(fèi),則記為nan
def purchase_return(data):
status=[]
for i in range(17):#循環(huán)17個(gè)月
if data[i]==1:#若本月消費(fèi)
if data[i+1]==1:#下個(gè)月也消費(fèi)
status.append(1)#就記為1
if data[i+1]==0:#下個(gè)月不消費(fèi)葫哗,就記為0
status.append(0)
else:
status.append(np.nan)
status.append(np.nan)
return pd.Series(status, index=columns_month)
pivoted_purchase_return=pivoted_purchase.apply(purchase_return,axis=1)#axis=1表示計(jì)算方向在行的方向上缔刹,左右運(yùn)算
pivoted_purchase_return.head()
df_purchase = (pivoted_purchase_return.sum() / pivoted_purchase_return.count()).reset_index()
df_purchase.columns = ['Date', 'PurchaseRate']
df_purchase['Date'] = df_purchase.Date.astype(str).apply(lambda x:x[:-3])
plt.figure(figsize = (15,5))
plt.plot(df_purchase.Date, df_purchase.PurchaseRate)
plt.xlabel('時(shí)間', fontsize=24)
plt.ylabel('回購(gòu)率', fontsize=24)
plt.title('回購(gòu)率的變化', fontsize=24);
- 上圖可以看出,在初期用戶的回購(gòu)率并不高劣针,1月的回購(gòu)率只有15%左右校镐,4月份起回購(gòu)率穩(wěn)定在30%左右。
從每月有回購(gòu)消費(fèi)的用戶數(shù)數(shù)據(jù)可以看出捺典,回購(gòu)用戶數(shù)整體有下降趨勢(shì)鸟廓。 - 對(duì)回購(gòu)率的分析,再次說(shuō)明了對(duì)于新用戶襟己,在其第一次消費(fèi)后的三個(gè)月內(nèi)是一段重要的時(shí)期引谜,需要營(yíng)銷策略積極引導(dǎo)其再次消費(fèi)及持續(xù)消費(fèi)。
- 另外擎浴,對(duì)于有持續(xù)消費(fèi)的老客员咽,也要適時(shí)推出反饋老客戶的優(yōu)惠活動(dòng),以加強(qiáng)老客的忠誠(chéng)度贮预。
8.4 分析留存率(3,7,15,30,90,365天為周期)
留存率:它指用戶在第一次消費(fèi)后贝室,有多少比率進(jìn)行第二次消費(fèi)。
消費(fèi)日期 - 第一次消費(fèi)日期 = 第二次消費(fèi)與第一次消費(fèi)的時(shí)間間隔 萌狂,再將天數(shù)轉(zhuǎn)化為數(shù)值
#分析留存率
#新建一個(gè)對(duì)象档玻,并增加用戶第一次消費(fèi)時(shí)間的列,merge將兩個(gè)dataframe合并
data_t=df[['用戶ID','購(gòu)買日期','訂單數(shù)','訂單金額']]
user_purchase_retention=pd.merge(left=data_t,right=orderdt_min.reset_index(),
how='inner',on='用戶ID',suffixes=('','_min'))
user_purchase_retention.head(5)
增加一列,表示訂單日期與用戶首次消費(fèi)日期間的間隔時(shí)間
#每一次消費(fèi)時(shí)間與第一次消費(fèi)時(shí)間間隔
user_purchase_retention['order_date_diff']=user_purchase_retention['購(gòu)買日期']-user_purchase_retention['購(gòu)買日期_min']
#將timedelta轉(zhuǎn)換為數(shù)值型
user_purchase_retention['date_diff']=user_purchase_retention.order_date_diff.apply(lambda x:x/np.timedelta64(1,'D'))
user_purchase_retention.head(5)
將時(shí)間差值分桶處理:
分成0~3天內(nèi)茫藏,3~7天內(nèi)误趴,7~15天……代表用戶當(dāng)前消費(fèi)時(shí)間距第一次消費(fèi)屬于哪個(gè)時(shí)間段
#將時(shí)間間隔分桶(0-3)(3-7)等
bin=[0,3,7,15,30,60,90,180,365]
user_purchase_retention['date_diff_bin']=pd.cut(user_purchase_retention.date_diff,bins=bin)
user_purchase_retention.head(10)
這里date_diff=0并沒(méi)有被劃分入0~3天,因?yàn)橛?jì)算的是留存率务傲,如果用戶僅消費(fèi)了一次凉当,留存率應(yīng)該是0枣申。另外,如果用戶第一天內(nèi)消費(fèi)了多次看杭,但是往后沒(méi)有消費(fèi)忠藤,也算作留存率0。
pivot_table數(shù)據(jù)透視楼雹,Pandas函數(shù)pivot_table會(huì)默認(rèn)刪除含有空值的行模孩,用dropna=False保持NaN的值。
#用戶第一次消費(fèi)之后贮缅,后續(xù)各時(shí)間段的消費(fèi)總額
pivoted_retention=user_purchase_retention.pivot_table(index='用戶ID',
columns='date_diff_bin',values='訂單金額',aggfunc=sum,dropna=False)
pivoted_retention.head()
獲得的結(jié)果是用戶在第一次消費(fèi)之后榨咐,在后續(xù)各時(shí)間段內(nèi)的消費(fèi)總額:
pivoted_retention.mean()#各時(shí)間段的平均消費(fèi)額
- 雖然后面時(shí)間段的金額高,但是它的時(shí)間范圍也寬廣谴供。從平均效果看块茁,用戶第一次消費(fèi)后的0~3天內(nèi),更可能消費(fèi)更多桂肌。
依舊將數(shù)據(jù)轉(zhuǎn)換成是否数焊,1代表在該時(shí)間段內(nèi)有后續(xù)消費(fèi),0代表沒(méi)有:
#1代表有消費(fèi)崎场,0代表沒(méi)有
pivoted_retention_trans=pivoted_retention.applymap(lambda x:1 if x>0 else 0)
pivoted_retention_trans
#每筆訂單離第一筆訂單的時(shí)間間隔
(pivoted_retention_trans.sum()/pivoted_retention_trans.count()).plot.bar(figsize=(10,5))
plt.xlabel('消費(fèi)時(shí)間間隔')
plt.title('留存率')
- 只有2.5%的用戶在第一次消費(fèi)的次日至3天內(nèi)有過(guò)消費(fèi)佩耳,3%的用戶在3~7天內(nèi)有過(guò)消費(fèi)。數(shù)字并不好看照雁,CD購(gòu)買確實(shí)不是高頻消費(fèi)行為蚕愤。有20%的用戶在第一次消費(fèi)后的三個(gè)月到半年之間有過(guò)購(gòu)買,27%的用戶在半年后至1年內(nèi)有過(guò)購(gòu)買饺蚊。
- 從運(yùn)營(yíng)角度看萍诱,CD機(jī)營(yíng)銷在服務(wù)新用戶的同時(shí),應(yīng)該注重用戶忠誠(chéng)度的培養(yǎng)污呼,放長(zhǎng)線掉大魚裕坊,在一定時(shí)間內(nèi)召回用戶購(gòu)買。
8.5 大客戶的貢獻(xiàn)率
因?yàn)橄M(fèi)行為有明顯的二八傾向燕酷,想知道高質(zhì)量用戶為消費(fèi)貢獻(xiàn)了多少份額籍凝?
8.5.1 用戶銷售額貢獻(xiàn)情況:
按照用戶id分組,對(duì)用戶的消費(fèi)金額進(jìn)行累計(jì)求和 苗缩,然后與總銷售額比饵蒂,得到比率,橫坐標(biāo)是用戶的id酱讶。
#先將用戶消費(fèi)金額按升序排列退盯,逐行計(jì)算用戶累計(jì)金額,最后一行是總消費(fèi)金額
user_money=df.groupby('用戶ID').訂單金額.sum().sort_values().reset_index()
user_money['money_cumsum']=user_money.訂單金額.cumsum()
money_total=user_money.money_cumsum.max()
#轉(zhuǎn)行成百分比
user_money['prop']=user_money.apply(lambda x:x.money_cumsum/money_total,axis=1)#apply用在每個(gè)行上
user_money.tail()
user_money.prop.plot()
plt.xlabel('用戶ID', fontsize=24)
plt.ylabel('比率', fontsize=24)
plt.title('用戶累計(jì)銷售額貢獻(xiàn)比', fontsize=24);
- 說(shuō)明:前20000個(gè)用戶,大約80%的用戶貢獻(xiàn)了40%的銷售額渊迁,20%的用戶貢獻(xiàn)了60%的銷售額
8.5.2 用戶銷量貢獻(xiàn)情況:
#先將用戶銷量按升序排列慰照,逐行計(jì)算用戶累計(jì)銷量,最后一行是總銷量
user_productsSum=df.groupby('用戶ID').訂單數(shù).sum().sort_values().reset_index()
user_productsSum['products_cumsum']=user_productsSum.訂單數(shù).cumsum()
productsSum_total=user_productsSum.products_cumsum.max()
#轉(zhuǎn)行成百分比
user_productsSum['prop']=user_productsSum.apply(lambda x:x.products_cumsum/productsSum_total,axis=1)#apply用在每個(gè)行上
user_productsSum.tail()
user_productsSum.prop.plot()
plt.xlabel('用戶ID', fontsize=24)
plt.ylabel('比率', fontsize=24)
plt.title('用戶累計(jì)銷量貢獻(xiàn)比', fontsize=24);
說(shuō)明:跟銷售額十分接近琉朽。
- 前20000名用戶貢獻(xiàn)了40%的消費(fèi)毒租,而后3500名用戶貢獻(xiàn)了60%的消費(fèi)。符合二八趨勢(shì)箱叁。也就是說(shuō)我們只要維護(hù)了這3500個(gè)用戶就可以把業(yè)績(jī)KPI完成60%墅垮,如果能把3500個(gè)用戶運(yùn)營(yíng)的更好就可以占比70%—80%之間。
九.結(jié)論
- 1.整體趨勢(shì):按年的月份趨勢(shì)銷量和銷售額在1-3月份相對(duì)極高蝌蹂,然后驟降噩斟,原因可能跟這段時(shí)間的大力促銷或與商品的季度屬性有關(guān)。
- 2.用戶個(gè)體特征:每筆訂單的金額和商品購(gòu)買量都集中在區(qū)間的低段水平孤个,都是小金額小批量進(jìn)行購(gòu)買,此類交易群體沛简,可在豐富產(chǎn)品線和增加促銷活動(dòng)提高轉(zhuǎn)換率和購(gòu)買率齐鲤。
- 3.大部分用戶的消費(fèi)總額和購(gòu)買總量都集中剛在低段,長(zhǎng)尾分布椒楣,這個(gè)跟用戶需求有關(guān)给郊,可以對(duì)商品進(jìn)行多元文化價(jià)值的賦予,增強(qiáng)其社交價(jià)值屬性捧灰,提高用戶的價(jià)值需求淆九。
- 4.用戶的消費(fèi)周期:有二次以上消費(fèi)的用戶,平均68天毛俏,所以在50天到60天期間炭庙,應(yīng)該對(duì)這批用戶進(jìn)行刺激召回,細(xì)致點(diǎn)煌寇,比如10天回復(fù)滿意度焕蹄,30天發(fā)放優(yōu)惠券,55天的時(shí)候提醒優(yōu)惠券的使用阀溶。
- 5.用戶的生命周期:有二次及以上消費(fèi)的用戶的平均生命周期是276天腻脏。用戶的生命周期分別在20天內(nèi)與400至500天間,應(yīng)該在20天內(nèi)對(duì)客戶進(jìn)行引導(dǎo)银锻,促進(jìn)其再次消費(fèi)并形成消費(fèi)習(xí)慣永品,延長(zhǎng)其生命周期;在100至400天的用戶击纬,也要根據(jù)其特點(diǎn)推出有針對(duì)性的營(yíng)銷活動(dòng)鼎姐,引導(dǎo)其持續(xù)消費(fèi)。
- 6..新客戶的復(fù)購(gòu)率約為6%,老客戶的復(fù)購(gòu)率在20%左右症见;新客戶的回購(gòu)率在15%左右喂走,老客戶的回購(gòu)率在30%左右,需要營(yíng)銷策略積極引導(dǎo)其再次消費(fèi)及持續(xù)消費(fèi)谋作。
- 7.用戶質(zhì)量:用戶個(gè)體消費(fèi)有一定規(guī)律性芋肠,大部分用戶的消費(fèi)集中在2000以下,用戶消費(fèi)反應(yīng)了2/8法則遵蚜,消費(fèi)排名前20%的用戶貢獻(xiàn)了80%的消費(fèi)額帖池。所以說(shuō),狠抓高質(zhì)量用戶是萬(wàn)古不變的道理吭净,這些高質(zhì)量客戶都是“會(huì)員”類型睡汹,需要專門為會(huì)員優(yōu)化購(gòu)物體驗(yàn),比如專線接聽(tīng)寂殉、特殊優(yōu)惠等等囚巴。
7.留存率來(lái)看,一半的用戶會(huì)流失友扰,所以應(yīng)該注重對(duì)用戶的忠誠(chéng)度的培養(yǎng)彤叉,比如打卡簽到,積分制度村怪,老用戶打折制度會(huì)員升級(jí)制度秽浇。