目錄
前言
一. 數(shù)據(jù)預(yù)處理
1.1 數(shù)據(jù)導(dǎo)入
1.2 數(shù)據(jù)清洗二. 月用戶消費(fèi)趨勢(shì)分析
2.1 每月消費(fèi)總金額
2.2 每月訂單總數(shù)
2.3 每月消費(fèi)總產(chǎn)品數(shù)
2.4 每月消費(fèi)人數(shù)
2.5 每月用戶平均消費(fèi)金額
2.6 每月用戶平均消費(fèi)次數(shù)三. 用戶個(gè)體消費(fèi)分析
3.1 用戶消費(fèi)金額和次數(shù)的散點(diǎn)圖
3.2 用戶消費(fèi)金額的分布圖
3.3 用戶消費(fèi)次數(shù)的分布圖
3.4 用戶累計(jì)消費(fèi)金額占比四. 用戶消費(fèi)行為分析
4.1 用戶第一次消費(fèi)(首購(gòu))
4.2 用戶最近一次消費(fèi)
4.3 新老客消費(fèi)比
4.4 用戶分層
前言
1铅碍、寫這篇報(bào)告的目的主要是為了練手疗绣,熟悉數(shù)據(jù)分析的流程感帅,把前期學(xué)的python數(shù)據(jù)分析庫(kù)等理論知識(shí)應(yīng)用到實(shí)際項(xiàng)目中奶稠,加深對(duì)理論知識(shí)的掌握度翎蹈。
2、數(shù)據(jù)來(lái)源于CDNow網(wǎng)站遮精,為用戶購(gòu)買CD的消費(fèi)明細(xì)酬土。
一. 數(shù)據(jù)預(yù)處理
先查看一下原始數(shù)據(jù):每一行代表一個(gè)用戶訂單的購(gòu)買明細(xì),共有用戶編號(hào)啃擦、購(gòu)買日期囊蓝、購(gòu)買產(chǎn)品數(shù)量、訂單消費(fèi)金額四個(gè)字段令蛉。但是原始數(shù)據(jù)中沒(méi)有包含表頭聚霜,我們導(dǎo)入數(shù)據(jù)時(shí)需要添加表頭。
1. 數(shù)據(jù)導(dǎo)入
import numpy as np
import pandas as pd
columns = [ 'user_id', 'order_dt', 'order_products', 'order_amount' ] # 定義表頭
df = pd.read_table('CDNOW_master.txt', names=columns, sep='\s+') # 分隔符為多個(gè)空格
此處注意原始數(shù)據(jù)使用空白符分割珠叔,需要指定分隔符俯萎,\s+代表任意多個(gè)空白符。
觀察數(shù)據(jù)樣本:
df.head()
查看數(shù)據(jù)類型信息运杭,觀察數(shù)據(jù)是否被正確識(shí)別:
df.info()
發(fā)現(xiàn)購(gòu)買日期order_dt為整數(shù)類型,需要進(jìn)行數(shù)據(jù)清洗函卒,將其轉(zhuǎn)換為日期類型辆憔。 沒(méi)有空值,不需要填補(bǔ)缺失值报嵌。
查看整體統(tǒng)計(jì)信息:
df.describe()
- 大部分訂單只購(gòu)買了少量商品(平均2.4)虱咧,50%的訂單購(gòu)買商品數(shù)量了在2個(gè)及以下,75%的訂單購(gòu)買商品數(shù)量在3個(gè)及以下锚国,最多的訂單購(gòu)買了99個(gè)商品腕巡,平均消費(fèi)商品數(shù)量存在一定極值干擾;
- 訂單平均交易金額35元血筑,中位數(shù)在25元绘沉,75%的訂單金額在43元及以下,訂單最大金額為1286豺总,有一定極值干擾车伞。
2. 數(shù)據(jù)清洗——類型轉(zhuǎn)化
將剛剛提到的購(gòu)買日期order_dt轉(zhuǎn)化為時(shí)間類型:
df.order_dt = pd.to_datetime(df.order_dt, format='%Y%m%d')
再次查看數(shù)據(jù)信息:order_dt成功轉(zhuǎn)化為時(shí)間類型。
二. 月用戶消費(fèi)趨勢(shì)分析
因?yàn)槭前丛路治鲇髟孕略鲆粋€(gè)月份字段并查看數(shù)據(jù)樣本:
df['month'] = df.order_dt.values.astype('datetime64[M]')
df.head()
可以看到month精確到了月份另玖,后面的日都變成了1號(hào)。然后按月分組數(shù)據(jù):
grouped_month = df.groupby('month')
2.1 每月消費(fèi)總金額
order_amount_month = grouped_month.order_amount.sum()
# 或者order_amount_month = grouped_month[['order_amount']].agg(['sum'])
order_amount_month.head()
可視化每月消費(fèi)總金額情況:
import matplotlib.pyplot as pet
%matplotlib inline
plt.style.use('ggplot') # 使用設(shè)計(jì)風(fēng)格ggplot
order_amount_month.plot()
消費(fèi)金額在前三個(gè)月達(dá)到最高峰,之后急劇下降谦去,1997年4月份之后每月消費(fèi)總金額比較平穩(wěn)慷丽,有輕微下降趨勢(shì)。
2.2 每月訂單總數(shù)
grouped_month.user_id.count().plot()
前三個(gè)月訂單總數(shù)量平均為10000筆左右鳄哭,后續(xù)月份平均每個(gè)月的訂單量在2500筆左右要糊。
2.3 每月消費(fèi)總產(chǎn)品數(shù)
grouped_month.order_products.sum().plot()
前三個(gè)月消費(fèi)總產(chǎn)品數(shù)達(dá)到最高峰,平均為24000左右窃诉,后續(xù)月份平均每月消費(fèi)產(chǎn)品量約在6000左右杨耙。
2.1、2.2飘痛、2.3的結(jié)果也可以通過(guò)透視圖獲得:
pt = df.pivot_table(index = 'month',
values = [ 'order_products', 'order_amount', 'user_id' ],
aggfunc = {'order_products' : 'sum',
'order_amount' : 'sum',
'user_id' : 'count'})
pt.order_amount.plot()
pt.order_products.plot()
pt.user_id.plot()
2.4 每月消費(fèi)人數(shù)
同一個(gè)月中一個(gè)用戶可能消費(fèi)多次珊膜,需要去除掉重復(fù)的user_id。
方法一
grouped_month.user_id.nunique().plot()
方法二
grouped_month.user_id.apply(lambda x : len( x.drop_duplicates() ) ).plot() # 同一個(gè)月中一個(gè)用戶可能消費(fèi)多次宣脉,需要去除掉重復(fù)的user_id
方法三:
df.groupby([ 'month', 'user_id']).count().reset_index().groupby('month').user_id.count().plot() # 先按照月份和用戶ID分組達(dá)到對(duì)用戶ID去重的目的
- 每月消費(fèi)人數(shù)低于每月訂單總數(shù)(即每月消費(fèi)次數(shù))车柠,但差異不大;
- 前三個(gè)月每月的消費(fèi)人數(shù)在8000-10000人左右塑猖,后續(xù)月份平均消費(fèi)人數(shù)不足2000竹祷。
2.5 每月用戶平均消費(fèi)金額
# 每月用戶平均消費(fèi)金額 = 總金額 / 每月消費(fèi)總?cè)藬?shù)
grouped_month.apply( lambda x : x.order_amount.sum() / x.user_id.nunique() ).plot()
前三個(gè)月平均金額稍低,后續(xù)月份每月用戶平均消費(fèi)金額在47-57之間波動(dòng)羊苟,變化不大塑陵。
2.6 每月用戶平均消費(fèi)次數(shù)
# 每月用戶平均消費(fèi)次數(shù) = 每月訂單總量 / 每月消費(fèi)總?cè)藬?shù)
grouped_month.apply( lambda x : x.user_id.count() / x.user_id.nunique() ).plot()
- 每月用戶平均消費(fèi)頻次在1.13-1.15之間,前三個(gè)月由于用戶大量涌入蜡励,部分用戶可能僅消費(fèi)了一次令花,導(dǎo)致頻次略低;
- 后續(xù)月份用戶平均消費(fèi)頻次比較平穩(wěn)凉倚,且略高于前3個(gè)月兼都。
三. 用戶個(gè)體消費(fèi)分析
觀察用戶消費(fèi)金額、購(gòu)買產(chǎn)品數(shù)量的描述統(tǒng)計(jì):
grouped_user = df.groupby('user_id')
grouped_user.sum().describe()
- 平均每用戶購(gòu)買了7張CD稽寒,但是中位數(shù)只有3扮碧,說(shuō)明小部分用戶購(gòu)買了大量CD;
- 用戶平均消費(fèi)106元杏糙,中位值為43慎王,75%分位數(shù)為106,剛好等于平均消費(fèi)搔啊,有25%的用戶消費(fèi)的比平均金額多柬祠,再看最大消費(fèi)金額為13990(CD狂熱愛好者啊)负芋,佐證了上面小部分用戶購(gòu)買了大量CD的結(jié)論漫蛔,數(shù)據(jù)存在極值干擾嗜愈。
3.1 用戶消費(fèi)金額和消費(fèi)次數(shù)的散點(diǎn)圖
grouped_user.sum().plot.scatter(x = 'order_products', y = 'order_amount' )
可以看到最后面兩個(gè)極值的存在拉大了圖形區(qū)域,使得密集區(qū)域集中在左下角莽龟。通過(guò)過(guò)濾排除極值干擾:
grouped_user.sum().query('order_products < 350').plot.scatter(x = 'order_products', y = 'order_amount')
散點(diǎn)圖呈現(xiàn)明顯的線性關(guān)系蠕嫁,可以推測(cè)CD產(chǎn)品比較單一,單價(jià)比較穩(wěn)定毯盈。
3.2 用戶消費(fèi)金額的分布圖
grouped_user.sum().order_amount.plot.hist(bins = 100)
plt.xlabel('order_amount') # 設(shè)置x軸的名稱
從直方圖可知剃毒,用戶消費(fèi)金額,絕大部分呈現(xiàn)集中趨勢(shì)搂赋,大部分用戶消費(fèi)金額在1500以內(nèi)赘阀,小部分異常值干擾了判斷。
使用切比雪夫定律(95%的數(shù)據(jù)位于其平均值+5標(biāo)準(zhǔn)差范圍之內(nèi))過(guò)濾異常值脑奠,由3.1的用戶消費(fèi)金額及購(gòu)買產(chǎn)品數(shù)量的描述性統(tǒng)計(jì)可知基公,95%的用戶消費(fèi)金額位于106+5240=1306范圍內(nèi):
grouped_user.sum().query('order_amount < 1306').order_amount.plot.hist(bins = 20)
3.3 用戶消費(fèi)次數(shù)的分布圖
同上,獲取過(guò)濾掉極值之后的用戶購(gòu)買產(chǎn)品數(shù)量分布:
grouped_user.sum().query('order_products < 100').order_products.plot.hist(bins = 20)
可以看出宋欺,大部分用戶僅購(gòu)買了1-5張CD轰豆,整體購(gòu)買數(shù)量和消費(fèi)金額成指數(shù)下降趨勢(shì)。
3.4 用戶累計(jì)消費(fèi)金額占比(百分之多少的用戶占了百分之多少的消費(fèi)額)
user_cumsum = grouped_user.sum().sort_values('order_amount').apply(lambda x : x.cumsum() / x.sum()) # 對(duì)每一列應(yīng)用apply里面的函數(shù)
user_cumsum.reset_index().order_amount.plot() # 重新設(shè)置索引方便作圖齿诞,x軸為索引
50%的用戶僅貢獻(xiàn)了約15%的消費(fèi)額酸休,消費(fèi)金額排名靠前的20%用戶貢獻(xiàn)了60%的消費(fèi)額。
四. 用戶消費(fèi)行為分析
4.1 用戶第一次消費(fèi)(首購(gòu))
備注:首購(gòu)是一個(gè)比較重要的維度祷杈,它和渠道等息息相關(guān)斑司, 尤其是客單價(jià)比較高用戶留存率又比較低的行業(yè), 可以通過(guò)首購(gòu)分析第一次購(gòu)買的用戶渠道但汞,然后拓展出運(yùn)營(yíng)的方式陡厘。
通過(guò)對(duì)用戶第一次購(gòu)買時(shí)間最小值的統(tǒng)計(jì)獲取用戶首購(gòu)時(shí)間分布情況:
grouped_user.min().order_dt.value_counts().plot()
用戶第一次購(gòu)買時(shí)間集中在前三個(gè)月,其中在2月中旬的時(shí)候有一次比較大的波動(dòng)特占。
4.2 用戶最近一次消費(fèi)
grouped_user.max().order_dt.value_counts().plot()
- 用戶最后一次購(gòu)買的分布比第一次分布廣;
- 大部分用戶最后一次購(gòu)買時(shí)間云茸,集中在前三個(gè)月是目,說(shuō)明很多用戶購(gòu)買了一次后就不再購(gòu)買;
- 隨著時(shí)間的遞增标捺,最后一次購(gòu)買數(shù)量也在遞增懊纳,消費(fèi)呈現(xiàn)流失上升的狀況。
4.3 新老客消費(fèi)比
4.3.1 多少用戶僅消費(fèi)了一次
求出用戶的購(gòu)買時(shí)間的最大值和最小值亡容,若相等嗤疯,說(shuō)明用戶僅消費(fèi)了一次:
user_life = grouped_user.order_dt.agg(['min', 'max'])
user_life.head()
(user_life['min'] == user_life['max']).value_counts()
超過(guò)一半的用戶,僅消費(fèi)了一次闺兢。
4.3.2 每月新客占比
grouped_month_user = df.groupby(['month', 'user_id']) # 按月和用戶ID分組
tmp = grouped_month_user.order_dt.agg(['min']).join(grouped_user.order_dt.min()) # 求出用戶在當(dāng)月首購(gòu)時(shí)間和用戶在所有時(shí)間段的首購(gòu)時(shí)間
tmp['is_new'] = (tmp['min'] == tmp['order_dt']) # 新增一列茂缚,是否首購(gòu)時(shí)間在當(dāng)月,即是否為新客
tmp.reset_index().groupby('month').apply(lambda x : x.is_new.sum() / x.user_id.count() ).plot() # 計(jì)算新客占比
新客集中在前三個(gè)月,后面消費(fèi)的均為老用戶脚囊。
4.4 用戶分層
R:最近一次消費(fèi)時(shí)間
F:消費(fèi)頻率
M:消費(fèi)金額
通過(guò)透視表獲取用戶RFM相關(guān)維度的信息:
rfm = df.pivot_table(index = 'user_id',
values = [ 'order_products', 'order_amount', 'order_dt' ],
aggfunc = {'order_dt' : 'max',
'order_amount' : 'sum',
'order_products' : 'sum'})
rfm.head()
求出相應(yīng)的R龟糕、F、M:
rfm['R'] = (rfm.order_dt.max() - rfm.order_dt) /np.timedelta64(1, 'D') # 把所有用戶order_dt的最大值作為現(xiàn)在的時(shí)間悔耘,求出距今天數(shù)
rfm.rename(columns = {'order_products' : 'F', 'order_amount' : 'M'}, inplace = True)
rfm.head()
將用戶在R讲岁、F、M三個(gè)維度上分為低于平均額度和高于平均額度的用戶(劃分標(biāo)準(zhǔn)根據(jù)不同業(yè)務(wù)設(shè)計(jì)不同):
rfm[['R', 'F', 'M']].apply(lambda x : x - x.mean()).head()
給用戶打標(biāo)簽:
def rfm_label(x): # 對(duì)每一行數(shù)據(jù)根據(jù)其rfm的值求出其label
level = x.apply(lambda x : '1' if x >= 0 else '0')
label = level.R + level.F + level.M
d = {
'111' : '重要價(jià)值客戶',
'011' : '重要保持客戶',
'101' : '重要發(fā)展客戶',
'001' : '重要保持客戶',
'110' : '一般價(jià)值客戶',
'010' : '一般保持客戶',
'100' : '一般發(fā)展客戶',
'000' : '一般挽留客戶'
}
result = d[label]
return result
rfm['label'] = rfm[['R', 'F', 'M']].apply(lambda x : x - x.mean()).apply(rfm_label, axis = 1)
ram.head()
可以看到衬以,用戶已經(jīng)都打上了相應(yīng)的標(biāo)簽缓艳。
rfm.groupby('label').sum()
rfm.groupby('label').count()
從RFM分層結(jié)果可知备籽,“重要保持客戶”為主要利潤(rùn)來(lái)源舶治,即最后一次消費(fèi)時(shí)間越晚,消費(fèi)頻次越高车猬,消費(fèi)額度越高的用戶是優(yōu)質(zhì)客戶霉猛。
用不同顏色區(qū)分不同標(biāo)簽的用戶:
rfm.loc[ rfm.label == '重要保持客戶', 'color'] = 'brown'
rfm.loc[ rfm.label == '重要發(fā)展客戶', 'color'] = 'grey'
rfm.loc[ rfm.label == '重要價(jià)值客戶', 'color'] = 'c'
rfm.loc[ rfm.label == '重要挽留客戶', 'color'] = 'r'
rfm.loc[ rfm.label == '一般保持客戶', 'color'] = 'k'
rfm.loc[ rfm.label == '一般發(fā)展客戶', 'color'] = 'y'
rfm.loc[ rfm.label == '一般價(jià)值客戶', 'color'] = 'm'
rfm.loc[ rfm.label == '一般挽留客戶', 'color'] = 'w'
rfm.plot.scatter('F', 'R', c=rfm.color)
從圖中可以看到大部分用戶的購(gòu)買頻次在200以內(nèi),少部分的極值可能會(huì)對(duì)我們使用平均值劃分RFM造成一定程度的偏差(平均值對(duì)大部分用戶來(lái)說(shuō)偏大)珠闰,所以如果使用平均值劃分應(yīng)該考慮到先根據(jù)切比雪夫定律剔除極值惜浅。