寫這本篇文章的目的是為了加深對數(shù)據(jù)分析的理解,文章以模仿為主,利用pandas,matplotlib進行數(shù)據(jù)處理和數(shù)據(jù)可視化分析假抄,數(shù)據(jù)來源和鯨社區(qū)分享的CDNow網(wǎng)站的用戶購買明細。一共有用戶ID丽猬,購買日期宿饱,購買數(shù)量,購買金額四個字段脚祟。
1.數(shù)據(jù)處理
2.用戶總體消費分析
3.用戶個體消費數(shù)據(jù)分析
4.用戶消費行為周期分析
5.用戶復購率與回購率
數(shù)據(jù)處理
導入數(shù)據(jù)
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from datetime import datetime
plt.style.use('ggplot')#使用自帶的風格進行美化
導入常用的庫
columns = ['user_id','order_dt','order_products','order_amount']
df = pd.read_table(r'C:\Users\m\Desktop\CDNOW_master.txt',names = columns,sep='\s+')
- 加載包和數(shù)據(jù)谬以,文件是txt格式,用read_table打開由桌,因為源數(shù)據(jù)不包括表頭为黎,所以需要賦予表頭字段,字符串是空格分隔行您,用\s+表示匹配任意空白符铭乾。
- 表頭字段分為用戶ID,購買日期娃循,訂單數(shù)炕檩,訂單金額來分析,基本上這四個字段就可以進行豐富的分析淮野。
#默認輸出前五行
df.head()
- 觀察數(shù)據(jù)捧书,order_dt列表示時間吹泡,但只是一串年月日的數(shù)字骤星,后續(xù)需要數(shù)據(jù)類型轉(zhuǎn)換。
- 數(shù)據(jù)中存在一個用戶同一天或不同天購買多次爆哑,如用戶ID為2在12號購買了兩次洞难,這個細節(jié)要特別留意。
描述性統(tǒng)計
#匯總各列統(tǒng)計信息
df.describe()
describe是描述統(tǒng)計揭朝,對用戶數(shù)據(jù)進行整體性判斷:
- 從描述信息中队贱,用戶每個訂單平均購買2.4個商品,每個訂單平均消費35元
- 購買商品的標準差為2.33潭袱,說明數(shù)據(jù)有一定的波動性柱嫌;中位數(shù)為2,75分位數(shù)為3,說明大部分訂單購買數(shù)量不多屯换。最大值為99编丘,購買量比較大与学。購買金額的情況差不多,75分位數(shù)為43嘉抓,大部分都集中在小額索守。
總體數(shù)據(jù)來看,大部分用戶都屬于小額抑片,也貢獻了收入的大頭卵佛,數(shù)據(jù)分布是呈長尾形態(tài),俗稱二八敞斋。
數(shù)據(jù)處理
df.info()
查看數(shù)據(jù)類型截汪、數(shù)據(jù)是否存在空值,原數(shù)據(jù)是很干凈的數(shù)據(jù)渺尘,沒有空值挫鸽。接下來進行時間數(shù)據(jù)類型轉(zhuǎn)換。
df['order_date'] = pd.to_datetime(df.order_dt,format="%Y%m%d")
df['month'] = df.order_date.values.astype('datetime64[M]')
數(shù)據(jù)類型的轉(zhuǎn)換:
- pd.to_datetime可以將數(shù)字轉(zhuǎn)換為時間類型鸥跟,format參數(shù)用于匹配丢郊。%Y匹配前四位數(shù)字1997,小寫y只匹配97医咨,%m匹配01枫匾,%d匹配01,返回結(jié)果為1997-01-01拟淮。
- astype可以將時間類型進行轉(zhuǎn)換干茉,[M]轉(zhuǎn)換為月份,這里取月份窗口作為消費頻率很泊。
小結(jié)
到該步驟角虫,我們通過描述性統(tǒng)計對數(shù)據(jù)有大概的了解,呈二八形態(tài)委造,也已經(jīng)將數(shù)據(jù)類型處理為合適的類型戳鹅,方便后續(xù)的分析。
用戶總體消費分析
按照月份維度來分析用戶總體消費趨勢
- 每月的總銷售額
- 每月的總銷量
- 每月的消費人數(shù)
month_grouped = df.groupby('month')
按月份進行統(tǒng)計分組
month_grouped.order_amount.sum().plot()
plt.title('總銷售額')
plt.show()
- 按月統(tǒng)計CD的銷量金額昏兆,從圖中可以知道枫虏,前三個月的銷量金額非常高。數(shù)據(jù)比較異常爬虱,而后期的銷量金額則很平穩(wěn)
month_grouped.order_dt.count().plot()
plt.title('消費次數(shù)')
plt.show()
- 圖中可知前三個月的消費訂單數(shù)在10000~12000筆區(qū)間中隶债,訂單數(shù)非常高漲,后期平均維持在2500筆左右跑筝。
month_grouped.order_products.sum().plot()
plt.title('總銷量')
plt.show()
- 和銷量金額一樣死讹,每月的產(chǎn)品銷量呈現(xiàn)早期銷量非常大,后期平穩(wěn)下降的趨勢曲梗。
三個折線圖的整體趨勢基本一致赞警,可以看出逛腿,前三個月的銷量特別高漲,而三月份之后驟然下降仅颇,而后趨于平穩(wěn)单默。為什么會出現(xiàn)驟然下降原因呢?第一假設用戶數(shù)據(jù)出現(xiàn)問題忘瓦,早期時間段的用戶中存在異常值搁廓。第二假設是各類促銷活動,但這里只有消費數(shù)據(jù)耕皮,所以無法判斷境蜕。
month_grouped.user_id.apply(lambda x:len(x.unique())).plot()
plt.title('消費人數(shù)')
plt.show()
另一方面,通過消費人數(shù)的折線圖看出在2月到3月消費人數(shù)稍有下降凌停,但總銷量與總銷量金額依然上升粱年,是不是說明3月份存在高價值的客戶。
小結(jié)
上面四個折線圖的整體趨勢一致罚拟,呈現(xiàn)二八形態(tài)台诗。通過消費人數(shù)分析了解到3月份存在高價值的客戶,也說明我們應該重點挖掘3月份中的用戶赐俗,重點發(fā)展高價值客戶拉队。
用戶個體消費數(shù)據(jù)分析
前面我們是按月份維度進行整體來看數(shù)據(jù)趨勢。接下來我們需要看個體消費能力如何阻逮,我們劃分了五個方向:
- 用戶消費金額粱快,消費次數(shù)的描述性統(tǒng)計
- 用戶消費金額,消費次數(shù)的散點圖
- 用戶消費金額的分布圖(二八法則)
- 用戶消費次數(shù)的分布圖
- 用戶累計消費金額的占比(百分之多少的用戶占了百分之多少的消費額)
用戶消費金額叔扼,消費次數(shù)的描述統(tǒng)計
用戶的描述性統(tǒng)計
group_user = df.groupby('user_id')
print(group_user.sum().describe())
從用戶角度來看事哭,每位用戶平均購買7張CD,購買量的最大值購買了1033張瓜富。用戶的平均消費金額是100元左右鳍咱,標準差為240。兩者結(jié)合分位數(shù)和最大值看食呻,平均數(shù)和75分位數(shù)接近流炕,存在小部分高消費用戶澎现,符合二八法則仅胞。
用戶消費金額和消費次數(shù)的散點圖
group_user.sum().plot.scatter(x='order_amount',y='order_products')
plt.title('用戶散點圖')
plt.show()
- 從圖上看用戶比較健康而且規(guī)律性很強,整體符合CD網(wǎng)站商品單一的銷售數(shù)據(jù)剑辫,金額和商品呈線性干旧,沒幾個離散點。
用戶消費金額的分布圖(二八法則)
group_user.sum().order_amount.plot.hist(bins = 20)
plt.show()
- 從圖中看用戶的消費呈集中趨勢妹蔽,可能是有個別的極大值干擾導致椎眯∧咏可以排除極大值再看看分布。
group_user.sum().query("order_amount <800").order_amount.plot.hist(bins = 20)
plt.show()
- 從直方圖圖可知编整,絕大部分用戶呈現(xiàn)集中在低的消費檔次舔稀,將近半數(shù)的用戶消費金額不超過40元,高消費用戶(>200元)不超過2000人掌测,高消費在圖中幾乎看不到内贮,符合消費行為的行業(yè)規(guī)律。
用戶消費次數(shù)的分布圖(二八法則)
group_user.sum().query("order_products <100").order_products.plot.hist(bins = 40)
plt.show()
- 大部分用戶購買CD的數(shù)量在7張內(nèi)汞斧,大量購買CD的用戶數(shù)量很低夜郁。
用戶累計消費金額的占比
前面的分析對用戶的消費行為有一個大概的了解,接下來分析用戶質(zhì)量粘勒。因為消費行為有明顯的二八傾向竞端,我們需要知道高質(zhì)量用戶為消費貢獻了多少份額。
user_amount = df.groupby('user_id').order_amount.sum().sort_values().reset_index()
user_amount['amount_cumsum'] = user_amount.order_amount.cumsum()
print(user_amount.tail())
- 按用戶的消費金額升序庙睡,使用cumsum累加函數(shù)事富。逐行計算累計的金額,獲取最后的總消費金額為2500315乘陪。
amount_total = user_amount.amount_cumsum.max()
user_amount['prop'] = user_amount.apply(lambda x:x.amount_cumsum / amount_total,axis = 1)
print(user_amount.tail())
轉(zhuǎn)換用戶貢獻消費金額百分比
user_amount.prop.plot()
plt.xlabel('用戶數(shù)量')
plt.ylabel('用戶累計貢獻百分比')
plt.show()
- 繪制趨勢圖赵颅,橫坐標是以貢獻金額大小排序的用戶,縱坐標則是用戶累計貢獻百分比暂刘。前面知道總體用戶為24000左右饺谬,圖中可以看到前20000個用戶貢獻40%,后面4000位用戶貢獻了60%谣拣,確實呈現(xiàn)二八傾向募寨。也就是說我們維護這4000個用戶就可以達到業(yè)績KPI完成60%。
小結(jié)
到此我們大概可以了解用戶個體消費呈現(xiàn)二八形態(tài)森缠,大部分用戶都屬于小金額用戶拔鹰,符合消費行業(yè)的行規(guī)律。通過用戶累計消費金額占比趨勢圖有大概4000個用戶貢獻了總體的60%贵涵,如果能把4000個用戶運營的更好就可以提高到占比70%左右列肢,更容易提高業(yè)績。
用戶消費行為周期分析
- 用戶第一次消費(首購)
- 用戶最后一次消費
- 新老客戶消費比
- 用戶生命周期
- 用戶購買周期
- 用戶復購率與回購率
新用戶第一次消費
group_user.month.min().value_counts()
- 按用戶分組求月份的最小值宾茂,即用戶消費行為中的第一次消費時間瓷马。圖中可知所有用戶的第一次消費都集中在前三個月。
用戶最后一次消費
group_user.month.max().value_counts()
group_user.month.max().value_counts().plot()
plt.xlabel('月份')
plt.ylabel('最后一次消費人數(shù)')
plt.show()
- 觀察用戶的最后一次消費時間跨晴。絕大部分數(shù)據(jù)依然集中在前三個月欧聘,后續(xù)的時間段內(nèi)有用戶消費,但增長緩慢遞增端盆,存在一定的用戶回購怀骤。
- 前面提到的第一假設的異常趨勢得到解釋费封,但這只是部分用戶的訂單數(shù)據(jù),所以有一定局限性蒋伦。
新舊用戶消費比
user_new_old = group_user.order_date.agg(['min','max'])
new_old = (user_new_old['min'] == user_new_old['max']).value_counts()
print(new_old)
- 按用戶分組弓摘,計算用戶第一消費和最后一次消費時間,如果新舊時間一致痕届,說明只消費了一次衣盾。統(tǒng)計數(shù)據(jù)可知有一半的用戶只消費一次。
plt.pie(x = new_old,
labels=['僅消費一次','多次消費'],
autopct= '%.1f%%',
shadow= True,
explode=[0.08,0],
textprops={'fontsize':11})
plt.title('新老用戶消費比')
plt.show()
- 繪制餅圖更直觀反映現(xiàn)象爷抓,超過一半用戶僅消費一次势决,這也說明留存用戶效果不好,營運效果不佳蓝撇。
用戶購買周期
order_diff = group_user.apply(lambda x:x['order_date']-x['order_date'].shift())
print(order_diff.head(10))
- 每個用戶的每次購買時間間隔果复,用戶1只購買一次,所以為空值渤昌,用戶2的第一筆訂單與第二筆訂單在同一天購買的虽抄。
order_diff.describe()
- 每個用戶的購買時間間隔平均是68天,間隔最長的是533天独柑。想要召回用戶迈窟,在60天左右的消費間隔也是比較好的。
消費周期分布
(order_diff/ np.timedelta64(1,'D')).hist(bins =20)
plt.show()
- 數(shù)據(jù)呈指數(shù)分布忌栅,大部分用戶的消費周期確實比較短车酣,低于100天。
用戶生命周期
orderdate_min = group_user.order_date.min()
orderdate_max = group_user.order_date.max()
user_life = orderdate_max-orderdate_min
print(user_life.head())
(orderdt_max-orderdt_min).describe()
- 所有的用戶平均生命周期有134天索绪,中位數(shù)為0天也就是說有一半用戶的生命周期只購買了一次湖员。接下來看一下分布情況。
((orderdate_max-orderdate_min)/np.timedelta64(1,'D')).hist(bins=15)
- 有一半的用戶只消費一次瑞驱,所以生命周期的大頭都集中在0天娘摔。
- 不妨將只消費了一次的新客排除,來計算所有消費過兩次以上的老客的生命周期唤反。
life_time = (orderdate_max - orderdate_min).reset_index()
print(life_time.head())
life_time['life_time'] = life_time.order_date / np.timedelta64(1,'D')
life_time[life_time.life_time > 0].life_time.hist(bins = 100)
plt.show()
- 這是雙峰趨勢圖凳寺。20天內(nèi)生命周期的用戶是一個高峰,但無法持續(xù)彤侍,在用戶首次消費30天內(nèi)應該盡量引導肠缨,延長其生命周期。少部分用戶集中在50天~300天拥刻,屬于普通型的生命周期怜瞒。高質(zhì)量用戶的生命周期父泳,集中在400天以后般哼,這已經(jīng)屬于忠誠用戶了吴汪。
用戶復購率與回購率
復購率
復購率的定義:在某時間窗口內(nèi)消費兩次及以上的用戶在總消費用戶中占比。這里的時間窗口是月蒸眠,如果一個用戶在同一天下了兩筆訂單漾橙,這里也將他算作復購用戶
pivoted_df = df.pivot_table(index= 'user_id',
columns='month',
values='order_date',
aggfunc='count').fillna(0)
print(pivoted_df.head())
- 每個用戶在每月的訂單數(shù),其中這里沒有消費過的標記0楞卡。
pivoted_df_tranf = pivoted_df.applymap(lambda x: 1 if x>1 else np.nan if x ==0 else 0 )
- 數(shù)據(jù)轉(zhuǎn)換一下霜运,消費2次以上記為1,消費1次記為0蒋腮,消費0次記為NAN
(pivoted_df_tranf.sum() / pivoted_df_tranf.count()).plot(figsize = (10,4))
plt.show()
- 這里用sum和count相除即可計算出復購率淘捡。因為這兩個函數(shù)都會忽略NaN,而NaN是沒有消費的用戶池摧。count計算的是總的消費用戶數(shù)焦除,sum計算了兩次以上的消費用戶。
- 圖上可以看到早期的復購率并不高作彤,是因為早期大量新用戶加入膘魄,如一月份的復購率只有6%左右。而到后期竭讳,這是的復購率就相對穩(wěn)定创葡,在20%左右。
- 單看新客和老客绢慢,復購率有三倍左右的差距灿渴。
回購率
接下來計算回購率,回購率是某一個時間窗口內(nèi)消費的用戶胰舆,在下一個時間窗口人就消費的占比逻杖。
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
print(pivoted_amount.head())
- 這里利用每個用戶每個月平均消費金額作為練習。
pivoted_purchase = pivoted_amount.applymap(lambda x:1 if x>1 else 0)
print(pivoted_purchase.head())
- 再次轉(zhuǎn)換數(shù)據(jù)思瘟,只要有過購買荸百,記為1,反之為0滨攻。
def purchase_return(data):
status = []
for i in range(17):
if data[i] == 1: #如本月消費
if data[i+1] == 1: #下個月也消費
status.append(1) #標記為1
if data[i+1] == 0: #下個不消費
status.append(0) #標記為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)
print(pivoted_purchase_return.head())
- 創(chuàng)建一個判斷函數(shù)够话。data是輸入的數(shù)據(jù),status是空列表光绕,用來保存用戶是否回購的字段女嘲。
- 判斷邏輯:如果用戶本月進行過消費,且下月消費過诞帐,記為1欣尼,沒有消費過是0。本月若沒有進行過消費,為NaN愕鼓,后續(xù)的統(tǒng)計中進行排除钙态。
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.show()
- 上圖可以看出聪蘸,在初期用戶的回購率并不高形娇,1月的回購率只有15%左右,4月份起回購率穩(wěn)定在30%左右商源,波動性也較強磺送。
- 對回購率的分析驻子,再次說明了對于新用戶,在其第一次消費后的三個月內(nèi)是一段重要的時期估灿,需要營銷策略積極引導其再次消費及持續(xù)消費崇呵。
- 另外,對于有持續(xù)消費的老客馅袁,也要適時推出反饋老客戶的優(yōu)惠活動演熟,以加強老客的忠誠度。
小結(jié)
到此用戶消費行為周期分析已完成司顿,通過新舊用戶消費比芒粹,發(fā)現(xiàn)CDNOw網(wǎng)站留存用戶的效果不高,營運效果不佳大溜,進一步通過用戶的復購率和回購率的分析化漆,說明在新用戶消費后的三個月是營銷的好時段,應做好營銷策略引導用戶再次消費以及持續(xù)消費钦奋,也要適當推出優(yōu)惠活動座云,保持老用戶的支持度。
到此CDNow網(wǎng)站用戶消費行為分析以完成付材,后續(xù)學習更多再來補充朦拖!