CD案例分析

本文主要是主要是根據(jù)用戶(hù)消費(fèi)記錄,分析用戶(hù)消費(fèi)行為,建立RFM模型,分析復(fù)購(gòu)率、回購(gòu)率等關(guān)鍵指標(biāo)。希望對(duì)其他產(chǎn)品的線上消費(fèi)數(shù)據(jù)分析有一定的借鑒價(jià)值。

一、項(xiàng)目背景

CDNOW是美國(guó)的一家網(wǎng)上唱片公司,成立于1994年,后來(lái)被貝塔斯曼音樂(lè)集團(tuán)收購(gòu)。

二、分析目標(biāo)

本次分析報(bào)告的數(shù)據(jù)來(lái)源于這家CD網(wǎng)站上的用戶(hù)消費(fèi)記錄,旨在分析用戶(hù)消費(fèi)行為,建立RFM模型,分析復(fù)購(gòu)率、回購(gòu)率等關(guān)鍵指標(biāo)。

三、主要分析框架

image.png

四、分析過(guò)程

準(zhǔn)備工作:

# 導(dǎo)入數(shù)據(jù)包
import pandas as pd
import numpy as np
# 導(dǎo)入數(shù)據(jù)
columns = ['user_id','order_dt','order_products','order_amount']
df = pd.read_table('bicycle_master.txt',names = columns,sep = '\s+',engine='python')
df.head()
# user_id:用戶(hù)ID
# order_dt:購(gòu)買(mǎi)日期
# order_products:購(gòu)買(mǎi)產(chǎn)品數(shù)
# order_amount:購(gòu)買(mǎi)金額
image.png
# 查看數(shù)據(jù)類(lèi)型及數(shù)據(jù)完整情況
df.info()
image.png

通過(guò)查看數(shù)據(jù)類(lèi)型發(fā)現(xiàn),order_dt的數(shù)據(jù)類(lèi)型是int64型,而非日期型,需要將其轉(zhuǎn)化為日期型

# 轉(zhuǎn)化日期格式
df['order_dt'] = pd.to_datetime(df.order_dt,format = "%Y%m%d")
# 新增一列記錄月,方便后續(xù)按月統(tǒng)計(jì)
df['month'] = df['order_dt'].values.astype('datetime64[M]')
df.head(1)
image.png
# 數(shù)據(jù)描述性統(tǒng)計(jì)
df.describe()
image.png

從描述性統(tǒng)計(jì)可知:

  • 大部分訂單只消費(fèi)了少量商品(平均2.4),有一定值干擾
  • 用戶(hù)的消費(fèi)金額比較穩(wěn)定,平均消費(fèi)35元,中位數(shù)25元,有一定極值的干擾,導(dǎo)致平均消費(fèi)被拉高,絕大多數(shù)訂單的消費(fèi)金額都小于35元

1. 用戶(hù)消費(fèi)趨勢(shì)分析

根據(jù)月份分組,分別對(duì)消費(fèi)額,購(gòu)買(mǎi)人數(shù),購(gòu)買(mǎi)量,消費(fèi)人數(shù)聚合

# 根據(jù)月份分組
grouped_month = df.groupby('month')
# 聚合獲得月消費(fèi)次數(shù)
order_month_amount = grouped_month.order_amount.sum()
# 聚合獲得月消費(fèi)金額,月消費(fèi)次數(shù),月產(chǎn)品購(gòu)買(mǎi)量
grouped_month_info = grouped_month[['order_amount','user_id','order_products']].agg({'order_amount':'sum','user_id':'count','order_products':'sum'})
# 重命名
grouped_month_info.rename(columns = {'order_amount':'月消費(fèi)金額','user_id':'月消費(fèi)次數(shù)','order_products':'月產(chǎn)品購(gòu)買(mǎi)量'},inplace = True)
# 求消費(fèi)次數(shù)
grouped_month_info['消費(fèi)次數(shù)'] = grouped_month['user_id'].unique().map(len)
# 重置索引
grouped_month_info = grouped_month_info.reset_index()
grouped_month_info.head()
image.png

導(dǎo)出數(shù)據(jù),PowerBI作圖

# 如果是日期類(lèi)型,導(dǎo)入Power BI會(huì)是時(shí)間戳格式,所以這里轉(zhuǎn)成字符串
grouped_month_info['month'] = grouped_month_info['month'].astype('str')
grouped_month_info.to_excel(r'group_month_infor.xlsx')
image.png

由上圖可知

  • 消費(fèi)金額在前三個(gè)月達(dá)到最高峰,后續(xù)消費(fèi)較為穩(wěn)定,有輕微下降趨勢(shì)
  • 產(chǎn)品購(gòu)買(mǎi)量在前三個(gè)月達(dá)到最高峰,后續(xù)消費(fèi)較為穩(wěn)定,有輕微下降趨勢(shì)
  • 前三個(gè)月消費(fèi)訂單人數(shù)在10000筆左右,后續(xù)月份的平均消費(fèi)人數(shù)則在2500人

2. 用戶(hù)個(gè)體消費(fèi)分析

2.1 用戶(hù)消費(fèi)金額,消費(fèi)次數(shù)的描述統(tǒng)計(jì)

對(duì)用戶(hù)分組聚合

grouped_user = df.groupby('user_id')
grouped_user.sum().describe()
image.png

根據(jù)用戶(hù)購(gòu)買(mǎi)數(shù)量看,max是1033,但是中位數(shù)只有3,而均值為7,所以可知有少部分的用戶(hù)購(gòu)買(mǎi)了大量的產(chǎn)品

2.2 用戶(hù)消費(fèi)金額和消費(fèi)次數(shù)的散點(diǎn)圖
對(duì)用戶(hù)分組,對(duì)訂單數(shù)及訂單金額求和求得用戶(hù)消費(fèi)次數(shù)和消費(fèi)金額
grouped_user_info = grouped_user.sum()
grouped_user_info.to_excel(r'.\臨時(shí)表\用戶(hù)個(gè)體消費(fèi)行為分析.xlsx')
image.png

消費(fèi)金額與產(chǎn)品消費(fèi)數(shù)量成正相關(guān)

2.3 用戶(hù)消費(fèi)金額的分布圖
# 獲取用戶(hù)消費(fèi)金額
grouped_user_sum_order_amount = grouped_user.sum()['order_amount']
# 消費(fèi)金額按照50分箱
grouped_user_sum_order_amount_lst = [i for i in range(0,int(grouped_user_sum_order_amount.max())+50,50)]
# 按照分箱規(guī)則對(duì)用戶(hù)消費(fèi)金額進(jìn)行劃分
grouped_user_sum_order_amount = pd.cut(grouped_user_sum_order_amount,bins = grouped_user_sum_order_amount_lst,labels = grouped_user_sum_order_amount_lst[1:])
# 導(dǎo)出數(shù)據(jù)
grouped_user_sum_order_amount.to_excel(r'grouped_user_sum_order_amount.xlsx')
image.png

從直方圖可知,用戶(hù)消費(fèi)金額,絕大部分呈現(xiàn)集中趨勢(shì),小部分異常值干擾了判斷,可以使用過(guò)濾操作排除異常

2.4 用戶(hù)消費(fèi)次數(shù)的分布圖

與消費(fèi)金額分布情況相同,對(duì)消費(fèi)次數(shù)進(jìn)行分區(qū)

#4. 用戶(hù)消費(fèi)次數(shù)的分布圖
grouped_user_sum_order_products = grouped_user.sum()['order_products']
grouped_user_sum_order_products_lst = [i for i in range(0,int(grouped_user_sum_order_products.max())+50,50)]
grouped_user_sum_order_products = pd.cut(grouped_user_sum_order_products,bins = grouped_user_sum_order_products_lst,labels = grouped_user_sum_order_products_lst[1:])
grouped_user_sum_order_products.to_excel(r'grouped_user_sum_order_products.xlsx')
image.png
2.5 用戶(hù)累計(jì)消費(fèi)金額占比情況

對(duì)用戶(hù)分組,對(duì)消費(fèi)金額排序后累加即可

# 排序后使用cumsum對(duì)消費(fèi)金額累加
user_cumsum = grouped_user.sum().sort_values('order_amount').apply(lambda x:x.cumsum()/x.sum())
user_cumsum.reset_index().order_amount.to_excel(r'user_cumsum_order_amount.xlsx')
image.png

3. 用戶(hù)消費(fèi)行為

3.1 用戶(hù)第一次消費(fèi)(首購(gòu))
# 按用戶(hù)分組,取每個(gè)用戶(hù)的最小日期,然后對(duì)最小日期計(jì)數(shù)并按照次數(shù)由大到小排序value_counts
grouped_user_dt_min = grouped_user.min()['order_dt'].value_counts().reset_index().rename(columns = {'index':'first_date'})
grouped_user_dt_min['first_date'] = grouped_user_dt_min['first_date'].astype('str')
grouped_user_dt_min.to_excel(r'grouped_user_dt_min.xlsx')
image.png
3.2 用戶(hù)最后一次消費(fèi)

與用戶(hù)首購(gòu)分布同理,獲取用戶(hù)最后一次購(gòu)買(mǎi)日期的分布

grouped_user_dt_max = grouped_user.max()['order_dt'].value_counts().reset_index().rename(columns = {'index':'last_date'})
grouped_user_dt_max['last_date'] = grouped_user_dt_max['last_date'].astype('str')
grouped_user_dt_max.to_excel(r'grouped_user_dt_max.xlsx')
image.png

大部分最后一次購(gòu)買(mǎi),集中在前三個(gè)月,大量用戶(hù)購(gòu)買(mǎi)了一次后就不再進(jìn)行購(gòu)買(mǎi)。

3.3 新老客戶(hù)消費(fèi)占比
3.3.1 多少用戶(hù)只消費(fèi)一次

通過(guò)判斷起始購(gòu)買(mǎi)日期與最后購(gòu)買(mǎi)日期,如果相等則任務(wù)是新客戶(hù),如果不等則為老客戶(hù)

user_life=grouped_user.order_dt.agg(['min','max'])
# 統(tǒng)計(jì)只消費(fèi)了一次的用戶(hù)
(user_life['min']==user_life['max']).value_counts()
image.png

可知,新客戶(hù)占比51.1%

3.3.2 每月新客占比

分別對(duì)月與客戶(hù)分組,獲取每月每個(gè)客戶(hù)第一次與最后一次購(gòu)買(mǎi)日期,然后判斷是否為新客,通過(guò)月份分組獲得新老客戶(hù)數(shù)量

# 按月與用戶(hù)分組,獲得首購(gòu)及最后一次購(gòu)買(mǎi)日期
group_um = df.groupby(['month','user_id'])['order_dt'].agg(['min','max'])
# 新老客判斷
group_um['new'] = (group_um['min'] == group_um['max'])
# 按月分組對(duì)新老客計(jì)數(shù)
group_um.reset_index().groupby('month')['new'].value_counts()
image.png
3.4 用戶(hù)分層RFM模型

RFM模型介紹:
RFM模型是衡量客戶(hù)價(jià)值和客戶(hù)創(chuàng)利能力的重要工具和手段。
R:最近一次消費(fèi) (Recency)
F:消費(fèi)頻率 (Frequency)
M:消費(fèi)金額 (Monetary)
將以上三個(gè)指標(biāo)分別拆分為二,這樣就產(chǎn)生了8個(gè)維度用戶(hù)客戶(hù)的分組。R為1 表示比均值大,離最早時(shí)間近,F(xiàn)為1 表示消費(fèi)金額比較多,M為1 表示消費(fèi)頻次比較多
'111':'重要價(jià)值客戶(hù)',
'011':'重要保持客戶(hù)',
'101':'重要發(fā)展客戶(hù)',
'001':'重要挽留客戶(hù)',
'110':'一般價(jià)值客戶(hù)',
'010':'一般保持客戶(hù)',
'100':'一般發(fā)展客戶(hù)',
'000':'一般挽留客戶(hù)',

# 將消費(fèi)記錄表轉(zhuǎn)透視表,user_id為行索引,分別對(duì)訂單日期取最大值,訂單金額匯總,訂單產(chǎn)品數(shù)求和。
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()
image.png
# 因?yàn)閿?shù)據(jù)日期距今天比較久遠(yuǎn),所以這里令表中日期的最大值為當(dāng)前日期
# 求R值
RFM['R'] = (RFM.order_dt.max() - RFM.order_dt)/np.timedelta64(1,'D')
# 重命名
RFM = RFM.rename(columns = {'order_amount':'M','order_products':'F'})
RFM.head()
image.png

將個(gè)用戶(hù)分組,按照RFM的均值作為標(biāo)準(zhǔn),比均值大就為1,比均值小就為0

# 設(shè)定函數(shù),如果
def rfm_fumc(x):
    level = x.apply(lambda x:'1' if x >= 0 else '0')
    label = level.R + level.F + level.M
    d = {
        '111':'重要價(jià)值客戶(hù)',
        '011':'重要保持客戶(hù)',
        '101':'重要發(fā)展客戶(hù)',
        '001':'重要挽留客戶(hù)',
        '110':'一般價(jià)值客戶(hù)',
        '010':'一般保持客戶(hù)',
        '100':'一般發(fā)展客戶(hù)',
        '000':'一般挽留客戶(hù)'}
    result = d[label]
    return result
# apply 默認(rèn)axis = 0,按列映射
RFM['label'] = RFM[['R','F','M']].apply(lambda x : x - x.mean()).apply(rfm_fumc,axis = 1)
RFM.to_excel(r'RFM.xlsx')
RFM.head()
image.png

image.png
3.5 用戶(hù)購(gòu)買(mǎi)周期(按訂單)
3.5.1 用戶(hù)消費(fèi)周期描述

購(gòu)買(mǎi)周期,即用戶(hù)每次購(gòu)買(mǎi)的間隔

# 利用shift將用戶(hù)的購(gòu)買(mǎi)日期向下偏移1行,然后相減就可以得到每次購(gòu)買(mǎi)的間隔日期
order_diff = grouped_user.apply(lambda x : x.order_dt - x.order_dt.shift())
# 然后描述性統(tǒng)計(jì)
order_diff.describe()
image.png
3.5.2 用戶(hù)消費(fèi)周期分布

對(duì)用戶(hù)的消費(fèi)周期進(jìn)行區(qū)間劃分,然后對(duì)劃分后的組進(jìn)行分類(lèi)計(jì)數(shù)即為消費(fèi)周期的分布

# 去掉相減后的單位days
order_diff_info = (order_diff/np.timedelta64(1,'D'))
# 指定分箱
order_diff_cut_lst = [i for i in range(0,int(order_diff_info.max())+1,10)]
# 按照分箱去分組劃分
order_diff_info_hist = pd.cut(order_diff_info,bins = order_diff_cut_lst,labels = order_diff_cut_lst[1:])
# 用10填充N(xiāo)aN。NaN為第一次購(gòu)買(mǎi),所以沒(méi)有周期
order_diff_info_hist = order_diff_info_hist.fillna(10)
order_diff_info_hist.to_excel(r'order_dt_diff_info.xlsx')
image.png

訂單周期呈指數(shù)分布
絕大部分用戶(hù)的購(gòu)買(mǎi)周期都低于100天

3.6 用戶(hù)生命周期分布

用戶(hù)生命周期即為最后一次購(gòu)買(mǎi)的日期減去第一次購(gòu)買(mǎi)的日期。
按照用戶(hù)分組,獲取第一次與最后一次夠嗎的日期,并求間隔

# 分組獲取第一次與最后一次購(gòu)買(mǎi)日期
user_life = grouped_user['order_dt'].agg(['min',max])
# 獲取購(gòu)買(mǎi)周期
user_life['user_life'] = user_life['max'] - user_life['min']
user_life['user_life'] = user_life['user_life']/np.timedelta64(1,'D')

對(duì)購(gòu)買(mǎi)周期進(jìn)行分組劃分,統(tǒng)計(jì)各分組的頻數(shù)可形成用戶(hù)周期的分布圖

user_life_info = user_life['user_life']
# 分箱,然后按照分箱分區(qū)劃分,對(duì)于只購(gòu)買(mǎi)一次的用戶(hù),不進(jìn)行處理,即為NaN,后續(xù)在處理的時(shí)候不會(huì)統(tǒng)計(jì)NaN
user_life_lst = [i for i in range(0,int(user_life_info.max()+10),10)]
user_life_info_hist = pd.cut(user_life_info,bins = user_life_lst,labels = user_life_lst[1:])
user_life_info_hist.to_excel(r'user_life_info_noNaN.xlsx')
image.png

4. 復(fù)購(gòu)率和回購(gòu)率分析

復(fù)購(gòu)率:自然月內(nèi),購(gòu)買(mǎi)多次的用戶(hù)占比
本分析,定義復(fù)購(gòu)為當(dāng)月多次購(gòu)買(mǎi)為復(fù)購(gòu)
回購(gòu)率:曾經(jīng)購(gòu)買(mǎi)過(guò)的用戶(hù)在某一時(shí)期的再次購(gòu)買(mǎi)的占比
本分析,定義上個(gè)月購(gòu)買(mǎi),這個(gè)月繼續(xù)購(gòu)買(mǎi)為回購(gòu)。即周期為1個(gè)月

4.1 復(fù)購(gòu)率

對(duì)df進(jìn)行用戶(hù)和月份的透視,值為用戶(hù)單月購(gòu)買(mǎi)的次數(shù)

# 以用戶(hù)為索引,月份為列,對(duì)訂單進(jìn)行計(jì)數(shù),對(duì)于空值填充0,得到的值就為用戶(hù)單月購(gòu)買(mǎi)的次數(shù)
pivoted_counts=df.pivot_table(index='user_id',
                             columns='month',
                             values='order_dt',
                             aggfunc='count').fillna(0)
pivoted_counts.head()
image.png

為了方便統(tǒng)計(jì),我們把用戶(hù)單月購(gòu)買(mǎi)次數(shù)大于等于2的設(shè)為1,表示復(fù)購(gòu)
只有一次購(gòu)買(mǎi)設(shè)置為0,表示有購(gòu)買(mǎi),沒(méi)有復(fù)購(gòu)
沒(méi)有購(gòu)買(mǎi)的設(shè)置為NaN,表示未購(gòu)買(mǎi),方便后續(xù)算復(fù)購(gòu)率

purchase_r=pivoted_counts.applymap(lambda x: 1 if x>1 else np.NaN if x==0 else 0)
purchase_r.head()
image.png

計(jì)算復(fù)購(gòu)率

# 每列的和即為當(dāng)月的復(fù)購(gòu)次數(shù),每列的計(jì)數(shù)即為當(dāng)月購(gòu)買(mǎi)客戶(hù)的數(shù)量
purchase_r_reshop = (purchase_r.sum()/purchase_r.count()).reset_index(name = 'reshop')
purchase_r_reshop['month'] = purchase_r_reshop['month'].astype(str)
purchase_r_reshop.to_excel(r'purchase_reshop.xlsx')
image.png
4.2 回購(gòu)率
#在用戶(hù)單月購(gòu)買(mǎi)次數(shù)的表的基礎(chǔ)上,將當(dāng)月購(gòu)買(mǎi)過(guò)標(biāo)記為1,未購(gòu)買(mǎi)過(guò)的標(biāo)記為0
df_purchase = pivoted_counts.applymap(lambda x : 1 if x > 0 else 0)
df_purchase.head()
image.png

接下來(lái)判斷是否回購(gòu),通過(guò)apply設(shè)置axis = 1,對(duì)每個(gè)用戶(hù)逐個(gè)映射。
先判斷該用戶(hù)本月是否購(gòu)買(mǎi),如果沒(méi)購(gòu)買(mǎi):填充N(xiāo)aN,進(jìn)行下一個(gè)月份的判斷;如果購(gòu)買(mǎi):則判斷下個(gè)月是否夠購(gòu)買(mǎi),如果購(gòu)買(mǎi)則即為復(fù)購(gòu)1,否則為未復(fù)購(gòu)0

def purchase_back(data):
    '''判斷每一個(gè)月是否是回購(gòu),根據(jù)上個(gè)月是否購(gòu)買(mǎi)來(lái)判斷,上個(gè)月消費(fèi)下個(gè)月沒(méi)有購(gòu)買(mǎi)就不是回購(gòu)'''
    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)
    # 第18個(gè)月補(bǔ)充N(xiāo)aN
    status.append(np.NaN)
    return status
indexs=df['month'].sort_values().astype('str').unique()
purchase_b = df_purchase.apply(lambda x :pd.Series(purchase_back(x),index = indexs),axis =1)
purchase_b.head()
image.png

計(jì)算各月的復(fù)購(gòu)率

# 對(duì)各列求和即為當(dāng)月復(fù)購(gòu)的次數(shù),對(duì)各列計(jì)數(shù)即為當(dāng)月購(gòu)買(mǎi)的次數(shù)
purchase_backshop = purchase_b.sum()/purchase_b.count()
purchase_backshop.index = purchase_backshop.index.astype('str')
purchase_backshop.to_excel(r'purchase_backshop.xlsx')
image.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

  • 本文是對(duì)CD案例的一個(gè)總結(jié),主要是根據(jù)用戶(hù)消費(fèi)記錄,分析用戶(hù)消費(fèi)行為,建立RFM模型,分析復(fù)購(gòu)率、回購(gòu)率等關(guān)鍵指標(biāo)...
    liliuxuan閱讀 524評(píng)論 0 0
  • 本次案例的數(shù)據(jù)來(lái)源于CDNOW,是美國(guó)的一家網(wǎng)上唱片公司,數(shù)據(jù)描述的是這家公司網(wǎng)站上的用戶(hù)消費(fèi)記錄,分析目標(biāo)旨在分...
    胖波波玻璃球閱讀 800評(píng)論 0 0
  • 數(shù)據(jù)集來(lái)源于CDnow網(wǎng)站的用戶(hù)購(gòu)買(mǎi)行為,數(shù)據(jù)集一共包含四個(gè)字段:user_id,購(gòu)買(mǎi)日期,購(gòu)買(mǎi)數(shù)量和購(gòu)買(mǎi)金額。屬...
    敢敢寶寶閱讀 1,082評(píng)論 0 6
  • 首先當(dāng)然要把該import的都全部Import進(jìn)來(lái)。 為了待會(huì)兒畫(huà)圖正常顯示中文。因?yàn)槲沂荕AC系統(tǒng),所以代碼跟W...
    曾立韜閱讀 1,289評(píng)論 0 2
  • 前言: 存在一份用戶(hù)在一家cd網(wǎng)站上的消費(fèi)記錄,對(duì)此進(jìn)行消費(fèi)情況及用戶(hù)行為分析。數(shù)據(jù)樣式: 數(shù)據(jù)來(lái)源:鏈接:htt...
    Gaafung峰閱讀 1,859評(píng)論 1 10

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