單車案例

本文是對單車案例的一個(gè)總結(jié)毁习,主要是根據(jù)用戶的消費(fèi)記錄,深入分析用戶消費(fèi)行為寒随,建立RFM模型糠悯,進(jìn)行用戶分層,發(fā)掘高價(jià)值用戶并進(jìn)行針對性管理和維護(hù)妻往,實(shí)現(xiàn)用戶運(yùn)營精細(xì)化互艾。

目錄

  • 分析背景
  • 分析思路
  • 分析過程
  • 總結(jié)

一、分析背景

數(shù)據(jù)來源于網(wǎng)上蒲讯,是用戶在一家單車網(wǎng)上18個(gè)月的消費(fèi)記錄

二忘朝、分析思路

單車案例分析思路.png

本文為可視化查看方便,使用Matplotlib來畫圖呈現(xiàn)判帮,也可以導(dǎo)出數(shù)據(jù)為csv局嘁,然后使用powerBI等BI工具畫圖查看

三溉箕、分析過程

1. 數(shù)據(jù)的導(dǎo)入觀察與清洗

  • 數(shù)據(jù)導(dǎo)入和觀察
import numpy as np
import pandas as pd
import datetime
df = pd.read_csv('bicycle_master.txt')
df.head()
1.PNG
df.info()
2.PNG

從上面可以看出數(shù)據(jù)

  • 數(shù)據(jù)以table鍵作為分隔符,需要進(jìn)行分隔符的解析
    可以使用pd.read_csv中的參數(shù)進(jìn)行解析悦昵,sep='\s+'肴茄,可以將table鍵和多個(gè)空格當(dāng)成一樣的分隔符
  • 數(shù)據(jù)是沒有列名的,需要提前指定列名稱
    使用 pd.read_csv()中names可以在讀取時(shí)指定列名稱
  • 日期列需要解析為日期格式
    可以使用pd.read_csv()中的parse_dates 解析指定的列為日期格式
  • 需要提取月的信息但指,后續(xù)需要By月進(jìn)行統(tǒng)計(jì)
    月信息提取有兩種方法:df.astype() 強(qiáng)制類型轉(zhuǎn)換和pd.to_datetime 指定類型日期轉(zhuǎn)換兩種方式寡痰,這里使用的df.astype()進(jìn)行強(qiáng)制轉(zhuǎn)換,datetime64[M],表示轉(zhuǎn)換為每月的第一天了棋凳,同理設(shè)置為[Y]就是每年的1月1日
    重新讀取如下
cols = ['user_id','date','quantity','money']
df = pd.read_table('bicycle_master.txt', sep='\s+', names=cols, parse_dates=[1])
df['month'] = df.date.values.astype('datetime64[M]')
df['year'] = df.date.values.astype('datetime64[Y]')
df.head()
3.PNG
df.info()
4.PNG

pd.to_datetime()應(yīng)用如下


5.PNG
  • 查看數(shù)據(jù)的缺失值和統(tǒng)計(jì)性描述情況
df.isnull().sum()
6.PNG
df.describe()
7.PNG
  • 數(shù)據(jù)中沒有缺失值
  • 可以看出大部分訂單只購買了少量商品(均值2.4, 3/4分位數(shù)是3)拦坠,有個(gè)別極值的干擾
  • 用戶的消費(fèi)金額較穩(wěn)定,平均消費(fèi)約35剩岳,75%用戶消費(fèi)43.7元贞滨,中位數(shù)25

2. 用戶消費(fèi)趨勢的分析(按月)
1) 每月的消費(fèi)總金額,對消費(fèi)金額求和:np.sum()
2)每月的產(chǎn)品購買數(shù)量拍棕,對消費(fèi)數(shù)量求和:np.sum()
3)每月的訂單量晓铆,對訂單進(jìn)行計(jì)數(shù):pd.count()
4) 每月的消費(fèi)人數(shù),對user_id進(jìn)行去重后計(jì)數(shù)绰播,pd.nunique()
5) 每月的用戶的平均消費(fèi)金額骄噪,對消費(fèi)金額的取平均,np.mean()

df_month = df.groupby('month').agg({'user_id':'nunique', 'date':'count', 'quantity':np.sum, 'money':[np.sum, np.mean]})
df_month
8.PNG

可以看出蠢箩,列名稱需要重新命名链蕊,且要重置索引

df_month.columns = ['user_count','order_count','quantity_sum','monetary_sum','monetary_mean']
df_month.reset_index(inplace=True)
df_month
9.PNG

6) 每月用戶平均消費(fèi)次數(shù)的趨勢,每月的訂單數(shù)/每月用戶人數(shù)

df_month['order_avguser'] = df_month['order_count'] / df_month['user_count']
df_month
捕獲10.PNG

7)畫圖忙芒,可視化查看

  • 月消費(fèi)總金額和月購買產(chǎn)品數(shù)量趨勢
# 畫圖展示
import matplotlib.pyplot as plt
%matplotlib inline
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
x = df_month['month']
y = df_month['monetary_sum']
y2 = df_month['quantity_sum']

plt.plot(x, y, 'm')
plt.ylabel('消費(fèi)金額')
plt.title('月消費(fèi)總金額趨勢')
plt.legend()
11.PNG
plt.plot(x, y2)
plt.ylabel('產(chǎn)品購買數(shù)量')
plt.title('月產(chǎn)品購買數(shù)量')
plt.legend()
12.PNG

從月消費(fèi)總金額和購買數(shù)量查看示弓,在前三個(gè)月呈上升趨勢讳侨,第三個(gè)月達(dá)到頂峰呵萨,后續(xù)每月消費(fèi)逐漸穩(wěn)定,趨于輕微下降趨勢

  • 月消費(fèi)人數(shù)和訂單數(shù)查看
# 月消費(fèi)人數(shù)和訂單數(shù)
x = df_month['month']
y3= df_month['user_count']
y4 = df_month['order_count']

plt.plot(x, y3, 'y', label='消費(fèi)人數(shù)')
plt.plot(x, y4, 'c', label='訂單數(shù)')
plt.legend()
13.PNG
  1. 前三個(gè)月的消費(fèi)人數(shù)和訂單數(shù)呈上升趨勢跨跨,前三個(gè)月的訂單數(shù)在1000左右潮峦,第三個(gè)月達(dá)到頂峰,后續(xù)趨于平穩(wěn)勇婴,呈輕微下降趨勢忱嘹,在2500左右
  2. 每月消費(fèi)人數(shù)低于訂單數(shù),但差異不大
  3. 前三個(gè)月每月的消費(fèi)人數(shù)在8000-10000之間耕渴,后續(xù)每月平均消費(fèi)人數(shù)2000不到
  • 平均消費(fèi)金額和消費(fèi)次數(shù)查看
x = df_month['month']
y5 = df_month['monetary_mean']
y6 = df_month['order_avguser']

plt.subplot(2,1,1)
plt.plot(x, y5, 'r', label='平均消費(fèi)金額')
plt.legend()
plt.subplot(2,1,2)
plt.plot(x, y6, 'b', label='平均訂單數(shù)')
plt.legend()
14.PNG
  1. 用戶的平均消費(fèi)金額呈波動(dòng)上升在11月達(dá)到頂峰后拘悦,趨于波動(dòng)下降,整體差異不大橱脸,在33-41之間
  2. 平均訂單數(shù)在前三月從1.1上升到1.3础米,后續(xù)趨于穩(wěn)定在1.3-1.4區(qū)間內(nèi)
    3. 用戶個(gè)體分析
    1) 用戶消費(fèi)金額和消費(fèi)數(shù)量的分布
    2) 用戶消費(fèi)金額的分布分苇,按消費(fèi)金額區(qū)間統(tǒng)計(jì)用戶人數(shù)
    3) 用戶消費(fèi)次數(shù)的分布,按消費(fèi)次數(shù)分布區(qū)間統(tǒng)計(jì)用戶人數(shù)
    4) 用戶累計(jì)消費(fèi)金額占比屁桑,百分之多少的用戶貢獻(xiàn)了百分之多少的消費(fèi)金額

1) 用戶消費(fèi)金額和消費(fèi)數(shù)量的分布

df_user = df.groupby('user_id').agg({'quantity':np.sum,'money':np.sum, 'date':'count'}).reset_index()
df_user.rename(columns={'date':'order_count'}, inplace=True)
df_user.describe()
15.PNG
  • 可以看出消費(fèi)數(shù)量quantity消費(fèi)數(shù)量和消費(fèi)金額Money 的平均值是16,240医寿,中位數(shù)是3,43;說明有個(gè)別用戶購買了數(shù)量較多的產(chǎn)品
  • 散點(diǎn)圖查看
df_user.plot.scatter('money', 'quantity', alpha=0.5, title='用戶的消費(fèi)金額和消費(fèi)數(shù)量')
16.PNG

從上圖中看出受極值的影響蘑斧,大部分的用戶購買金額在4000以下靖秩,有12位用戶累計(jì)購金額大于4000

df_user1 = df_user[df_user['money'] < 4000]
plt.scatter(df_user1['money'],df_user1['quantity'], c='c', alpha=0.5)
plt.title('用戶的消費(fèi)金額和消費(fèi)數(shù)量散點(diǎn)圖')
plt.xlabel('消費(fèi)金額')
plt.ylabel('消費(fèi)數(shù)量')
plt.legend()
17.PNG

2) 用戶消費(fèi)金額的分布,按消費(fèi)金額區(qū)間統(tǒng)計(jì)用戶人數(shù)
將用戶消費(fèi)金額分組統(tǒng)計(jì)竖瘾,查看在哪個(gè)區(qū)間內(nèi)用戶人數(shù)最多沟突;使用pd.cut可以自動(dòng)將數(shù)據(jù)劃分區(qū)間或者按指定的數(shù)據(jù)列表進(jìn)行劃分,pd.cut劃分時(shí)每組包含右邊的數(shù)值捕传,不包含左邊的數(shù)值

bi = [x for x in range(0, int(df_user.money.max())+50, 50)]
df_user['money_b'] = pd.cut(df_user['money'], bins=bi, labels=bi[1:])
df_user.head()
18.PNG

可以看出在對用戶消費(fèi)金額分組后事扭,金額標(biāo)簽一欄存在缺失值,因?yàn)槲覀兊膭澐质菑?開始的乐横,pd.cut劃分含右不含左求橄,所以0的數(shù)值會(huì)顯示為缺失


19.PNG

金額為0 的數(shù)據(jù)是一些異常數(shù)據(jù),可以刪除這些數(shù)據(jù)后再進(jìn)行統(tǒng)計(jì)

df_user_2 = df_user.dropna(axis=0)
df_user_22 = df_user_2.groupby('money_b').agg({'user_id':'count'}).reset_index()
df_user_22['money_label'] = df_user_22.money_b.astype('int')
df_user_22.sort_values('money_label',inplace=True)
df_user_22.plot.line('money_label','user_id')
20.PNG
  • 直接使用分組后的數(shù)據(jù)畫圖時(shí)葡公,bar圖無法直觀呈現(xiàn)罐农,暫時(shí)使用折線圖,可以出當(dāng)消費(fèi)金額大于2000時(shí)催什,用戶人數(shù)趨向0涵亏,有極值干擾。
  • 使用切比雪夫定理過濾掉極值的影響

切比雪夫定理

  1. 所有數(shù)據(jù)中蒲凶,至少有3/4(或75%)的數(shù)據(jù)位于[平均數(shù)]2個(gè)標(biāo)準(zhǔn)差范圍內(nèi)气筋。
  2. 所有數(shù)據(jù)中,至少有8/9(或88.9%)的數(shù)據(jù)位于平均數(shù)3個(gè)標(biāo)準(zhǔn)差范圍內(nèi)旋圆。
  3. 所有數(shù)據(jù)中宠默,至少有24/25(或96%)的數(shù)據(jù)位于平均數(shù)5個(gè)標(biāo)準(zhǔn)差范圍內(nèi) [2] 。
    金額平均值的5個(gè)標(biāo)準(zhǔn)差:(mean = 106 ,std = 241)106+5*241=1311


    21.PNG

    過濾前:280組數(shù)據(jù)灵巧,過濾后只有27組數(shù)據(jù)

#畫圖
x = df_user_23['money_label']
y = df_user_23['user_id']
x1 = range(len(df_user_23['money_label']))

plt.bar(x1, y, width=0.8)
plt.xlabel('消費(fèi)金額')
plt.ylabel('用戶量')
plt.xticks(x1,df_user_23['money_label'], fontsize=9, rotation=90)
plt.title('用戶消費(fèi)金額頻次')
22.PNG

從直方圖可知搀矫,用戶消費(fèi)金額,絕大部分呈現(xiàn)集中趨勢

3) 用戶消費(fèi)次數(shù)的分布刻肄,按消費(fèi)次數(shù)分布區(qū)間統(tǒng)計(jì)用戶人數(shù)
按照如上同樣的方法進(jìn)行劃分小組瓤球,再分組統(tǒng)計(jì)

order_count_label = [x for x in range(0, int((df_user['order_count']).max()+1))]
df_user['order_count_label'] = pd.cut(df_user['order_count'],bins=order_count_label, labels=order_count_label[1:])
#分組后的標(biāo)簽為目錄格式,需要轉(zhuǎn)換為整型數(shù)據(jù)敏弃,以便后面畫圖使用
df_user['order_count_label'] = df_user.order_count_label.astype('int')
#按消費(fèi)次數(shù)分組求和
df_user_order = df_user.groupby('order_count_label').agg({'user_id':'count'}).reset_index().sort_values('order_count_label')
df_user_order.rename(columns={'user_id':'user_count'}, inplace=True)
df_user_order.plot.line('order_count_label','user_count')
23.PNG

從上圖可以看出卦羡,消費(fèi)次數(shù)也受極值的影響,同樣使用切比雪夫定理進(jìn)行過濾。

# 3+5*5
df_user_order_28 = df_user_order[df_user_order['order_count_label']<28]
x = range(len(df_user_order_28['order_count_label']))
x1 = df_user_order_28['order_count_label']
y = df_user_order_28['user_count']

# 畫直方圖時(shí)注意绿饵,可以先使用區(qū)間的長度按順序來畫圖逝薪,再使用區(qū)間的標(biāo)簽映射x軸原先使用的順序
plt.bar(x, y, width=0.8, color='c')
plt.xlabel('消費(fèi)次數(shù)')
plt.ylabel('用戶量')
plt.xticks(x, x1)
plt.title('用戶消費(fèi)次數(shù)頻次')
plt.legend()
24.PNG

可以看出用戶消費(fèi)次數(shù)集中在一次
4) 用戶累計(jì)消費(fèi)金額曲線
累計(jì)消費(fèi)金額可以使用pd.consum()來計(jì)算

# 累計(jì)消費(fèi)金額曲線 
df_user_cumsum_money = df_user.sort_values('money').money.cumsum() / df_user.sort_values('money').money.sum()
# 重置索引,和重命名列
df_user_cumsum_money = df_user_cumsum_money.reset_index().rename(columns={'index':'user_id','money':'money'})

# 畫圖準(zhǔn)備
y3 = df_user_cumsum_money['money']
x3 = range(df_user_cumsum_money.shape[0])
# 求中位數(shù)
y4 = [np.median(y3) for x in x3]

plt.plot(x3, y3, 'm')
plt.plot(x3, y4, 'r--', label='人數(shù)中位數(shù)')
plt.xlabel('消費(fèi)人次')
plt.ylabel('消費(fèi)金額占比')
plt.title('累積消費(fèi)金額曲線')
plt.legend()

25.PNG

26.PNG

由上可以看出蝴罪,按照用戶消費(fèi)金額進(jìn)行升序排序董济,50%的用戶僅貢獻(xiàn)10%的消費(fèi)金額,15%的用戶貢獻(xiàn)了60%的消費(fèi)金額
4. 用戶消費(fèi)行為

  1. 首購時(shí)間分布
  2. 最后一次購買時(shí)間分布
  3. 每月新客占比
  4. 用戶RFM模型分層
  5. 新要门、老虏肾、活躍、流失欢搜、回流用戶分布情況
  6. 用戶購買周期分布封豪,按兩次購買時(shí)間的間隔
  7. 用戶生命周期分布,首購和最后一次購買消費(fèi)時(shí)間

1)用戶首購分布
即每個(gè)用戶購買時(shí)間的最小值,再根據(jù)時(shí)間統(tǒng)計(jì)用戶人數(shù)炒瘟,除了使用分組統(tǒng)計(jì)groupby外吹埠,series的df.date.value_counts()也可以實(shí)現(xiàn)統(tǒng)計(jì)每個(gè)日期的人數(shù)

# 用戶首購
df_user_a = df.groupby('user_id').agg({'date':np.min}).date.value_counts().reset_index()
df_user_a = df_user_a.rename(columns={'index':'first_date', 'date':'user_count'})
print(df_user_a.head())
df_user_a.plot.line('first_date','user_count', title='用戶首購分布')
27.PNG

可以看到用戶的首購人數(shù)在1月到2月初是上升的,從2月中旬后就開始逐漸下降
2) 用戶最后一次消費(fèi)疮装,方法同上

# 用戶最后一次消費(fèi)
df_user_b = df.groupby('user_id').agg({'date':np.max}).date.value_counts().reset_index()
df_user_b.rename(columns={'index':'last_date','date':'user_count'}, inplace=True)
print(df_user_b.head())
df_user_b.plot.line('last_date', 'user_count', title='用戶最后一次購買分布')
28.PNG
  • 在3月份后缘琅,用戶最后一次購買分布斷崖式下跌,可以理解用戶流失也在3月份斷崖式下跌廓推;
  • 一開始用戶迅猛增長數(shù)量比較多流失的也比較多刷袍,后面沒有用戶 用戶最后一次購買的分布比第一次分布廣
  • 大部分最后一次購買,集中在前三個(gè)月樊展,說明很多用戶購買了一次后就不再進(jìn)行購買
  • 隨著時(shí)間的遞增呻纹,最后一次購買數(shù)量也在遞增,消費(fèi)呈現(xiàn)流失上升的狀況(這也是正常专缠,隨著時(shí)間的增長,可能運(yùn)營沒跟上哥力,或者用戶忠誠度下降了)

3)統(tǒng)計(jì)多少用戶僅消費(fèi)一次嘁圈,新老客戶的占比

# 查看多少用戶只購買了一次
df_user_d = df.groupby('user_id').date.agg([np.min, np.max])
df_user_d2 = (df_user_d['amax'] == df_user_d['amin']).value_counts()
df_user_d2
29.PNG
  • 將近一半的用戶僅購買了一次
df_user_d2 = df_user_d2.reset_index()
df_user_d2.columns = ['客戶', 'count']
df_user_d2.replace({'客戶':{0:'老客戶',1:'新客戶'}}, inplace=True)
df_user_d2.set_index('客戶',inplace=True)
df_user_d2.plot.pie('count',autopct='%.1f%%', radius = 1, startangle = 90, title='新老客戶消費(fèi)比', label='客戶')
30.PNG
  • 每月的新客比
    按月分組下的userid分組,求每月的最早購買日期和最晚消費(fèi)日期
# 每月新客比,只在每個(gè)月內(nèi)看用戶是否復(fù)購,如果沒有復(fù)購怠惶,算作新客
df_user_e = df.groupby(['month','user_id']).date.agg([np.min, np.max])
# 當(dāng)首購時(shí)間和末購時(shí)間相同則為新客戶
df_user_e['new'] = (df_user_e['amin'] == df_user_e['amax'])
df_user_e = df_user_e.reset_index().groupby('month').new.value_counts()
df_user_e2 = pd.DataFrame(df_user_e)

# 多重索引的處理,先提取原來的索引數(shù)據(jù)涨缚,再刪除掉多重索引
df_user_e2['flag'] = df_user_e2.index.droplevel('month')
df_user_e2['month1'] = df_user_e2.index.droplevel('new')
df_user_e2.index = df_user_e2.index.droplevel()
df_user_e3 = df_user_e2.reset_index(drop=True)

#標(biāo)簽的映射
df_user_e3['客戶'] = df_user_e3.flag.map({True:'新客戶', False:'老客戶'})
# 數(shù)據(jù)合并,將新客戶和老客戶分列展示
df_user_e4 = pd.merge(df_user_e3[df_user_e3['客戶'] == '新客戶'], df_user_e3[df_user_e3['客戶'] == '老客戶'],how='outer',on='month1')
# 計(jì)算新客比
df_user_e4['新客比'] = df_user_e4.apply(lambda x: x.new_x/(x.new_x+x.new_y), axis=1)
# 畫圖
df_user_e4.plot.line(x='month1', y='新客比', title='每月新客比')
31.PNG

柱狀圖呈現(xiàn)每月新客比

import matplotlib.pyplot as plt
%matplotlib inline

x = df_user_e4['month1'].astype('str')
x1 = np.arange(len(x))
y1 = df_user_e4['new_x']
y2 = df_user_e4['new_y']

plt.bar(x1, y1, color='m', width=0.25, label='新客戶')
plt.bar(x1+0.25, y2, color='b', width=0.25, label='老客戶')
plt.xticks(x1, x, rotation=-45)
plt.legend()
32.PNG

可以看到前三個(gè)月新客占比大于0.85脓魏,后面每個(gè)月新客占比趨于穩(wěn)定茂翔,說明大部分用戶每個(gè)月只購買一次

4)RFM模型


RFM模型.PNG
# 用戶分層:RFM珊燎,R最后一次消費(fèi)悔政,F(xiàn):消費(fèi)次數(shù)谋国,購買數(shù)量芦瘾,M:消費(fèi)金額
rfm = df.groupby('user_id').agg({'date':np.max, 'quantity':np.sum, 'money':np.sum}).reset_index()

#最近一次消費(fèi)時(shí)間距最近的天數(shù)近弟,因案例中的時(shí)間過于遠(yuǎn),所以采用案例中的最大時(shí)間做參考
import datetime
# -(rfm['date'] -np.datetime64('today','D')) / np.timedelta64(1, 'D')
rfm['R'] = (rfm['date'] -rfm.date.max()) / np.timedelta64(1, 'D')
# 列名重命名
rfm = rfm.rename(columns={'quantity':'F','money':'M'})
rfm.head()
33.PNG
# 歸一化,將RFM三個(gè)參數(shù)處理為中心化迫摔,零均值化句占,方便后續(xù)數(shù)據(jù)分層
rfm1 = rfm[['R','F','M']].apply(lambda x:x - x.mean())
rfm1.head()
34.PNG
# 標(biāo)簽映射
level = rfm1.applymap(lambda x :'1' if x >=0 else '0')
label = level.R + level.F + level.M
d = {
        '111':'重要價(jià)值客戶',
        '011':'重要喚回客戶',
        '101':'重要深耕客戶',
        '001':'重要挽留客戶',
        '110':'潛力客戶',
        '100':'新客戶',
        '010':'一般維持客戶',
        '000':'流失客戶' 
    }
rfm['level'] = label.map(d)
rfm['color'] = rfm.level.apply(lambda x :'重要價(jià)值客戶' if x=='重要價(jià)值客戶' else '非重要價(jià)值客戶')
rfm.head()
35.PNG

畫圖查看纱烘,主要查看重要價(jià)值客戶和非重要價(jià)值客戶的分布

import matplotlib.pyplot as plt
%matplotlib inline
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False

plt.scatter(rfm[rfm['color']=='重要價(jià)值客戶'].F, rfm[rfm['color']=='重要價(jià)值客戶'].R, c = 'c',label='重要', alpha=0.5)
plt.scatter(rfm[rfm['color']=='非重要價(jià)值客戶'].F, rfm[rfm['color']=='非重要價(jià)值客戶'].R, c = 'm',alpha=0.5,label='非重要')

plt.xlabel('F')
plt.ylabel('R')
plt.title('客戶標(biāo)簽分布')
plt.legend()
36.PNG

49.PNG
  • 從RFM 分層可知,大部分用戶是重要保持客戶帆阳,但是這是由于極值的影響
  • 所以 RFM 的劃分標(biāo)準(zhǔn)應(yīng)該以業(yè)務(wù)為準(zhǔn),也可以通過切比雪夫去除極值后求均值至扰,并且 RFM 的各個(gè)劃分標(biāo)準(zhǔn)可以都不一樣

5)新敢课、老直秆、活躍切厘、流失疫稿、回流用戶分布情況
按每個(gè)用戶每個(gè)月是否有消費(fèi)進(jìn)行判斷

# 用戶生命周期遗座, userid為索引途蒋,月為列号坡,求每月的消費(fèi)次數(shù)宽堆,這里缺失值使用0填充
pivot_count = pd.pivot_table(df, index='user_id', columns='month', values='date',
          aggfunc='count').fillna(0)
# 有消費(fèi)為1畜隶,無消費(fèi)為0
df_purchase = pivot_count.applymap(lambda x:1 if x>0 else 0)
df_purchase.head()
37.PNG

判斷用戶分布狀況

  • 新用戶:之前從沒購買籽慢,也就是之前月的購買次數(shù)為0
  • 活躍用戶:這個(gè)周期和上個(gè)周期都購買了箱亿,且不是新客戶
  • 回流用戶:上個(gè)周期沒買极景,這個(gè)周期買了盼樟,且不是新客戶
  • 流失用戶:本周期沒有購買晨缴,且不是新客戶
  • 未注冊:從未購買過
  • return:回流
  • new:新客
  • unreg:未注冊
  • active:活躍
  • unactive:流失
def status_m(data):
    status = []
    for i in range(18):
        if len(status) ==0:
            if data[i] == 1:
                status.append('new')
            else:
                status.append('unreg')

        else:
            if data[i] ==1:
                if status[i-1] == 'unreg':
                    status.append('new')
                elif status[i-1] == 'unactive':
                    status.append('return')
                else:
                    status.append('active')
            else:
                if status[i-1] == 'unreg':
                    status.append('unreg')
                else:
                    status.append('unactive')

    return status

p1 = df_purchase.apply(status_m, axis=1)

#將未注冊的用戶使用np.nan替換,從未購買稍途,這樣count計(jì)算人數(shù)時(shí)不會(huì)計(jì)算在內(nèi)
p2 = p1.replace('unreg',np.nan).apply(lambda x :pd.value_counts(x))
#填充np.nan為0械拍,方便后續(xù)畫圖
p_p=  p2.fillna(0).T
p_p.head()
38.PNG

畫圖查看用戶分布情況

from matplotlib import pyplot as plt
label = ['active','new','return','unactive']
y1 = p_p.active
y2 = p_p.new
y3 = p_p['return']
y4 = p_p.unactive
plt.stackplot(p_p.index, y1, y2,y3, y4, labels=['active','new','return','unactive'],alpha=0.4)
plt.title('用戶分層')
plt.legend()
39.PNG

可以看出前三個(gè)月新增用戶和回流用戶達(dá)到最大,3月之后幾乎無新客戶迄损,回流用戶和活躍用處于基本穩(wěn)定的狀態(tài)芹敌,不活躍用戶3月份后占了大部分

  • 計(jì)算用戶分布的占比
# 求出所有用戶的占比
p2.fillna(0).apply(lambda x : x/x.sum(), axis=0).T.head()
40.PNG
  • 前三個(gè)月有大量新用戶涌入氏捞,新用戶占比很高幌衣,而后面幾個(gè)月不活躍用戶占比非常高豁护,普遍在90%以上楚里。
  • 活躍用戶班缎,持續(xù)消費(fèi)的用戶达址,對應(yīng)的是消費(fèi)運(yùn)營的質(zhì)量沉唠。
  • 回流用戶满葛,之前不消費(fèi)嘀韧,本月才消費(fèi)锄贷,對應(yīng)的是喚回運(yùn)營肃叶。
  • 不活躍用戶因惭,對應(yīng)的是流失

6)用戶購買周期的分布

# 用戶購買周期
order_diff = df.groupby('user_id').apply(lambda x :x.date - x.date.shift())
# 將間隔日期轉(zhuǎn)換為數(shù)值
order_diff_i = order_diff / np.timedelta64(1,'D')
order_diff_i.describe()
# count    46089.000000
# mean        68.973768
# std         91.033032
# min          0.000000
# 25%         10.000000
# 50%         31.000000
# 75%         89.000000
# max        533.000000
# Name: date, dtype: float64

# 將間隔日期分組切割
ls = [i for i in range(0, int(order_diff_i.max())+10,10)]
order_diff_i1 = pd.cut(order_diff_i, bins=ls, labels=ls[1:]).fillna(10)
# 按切割后的每組統(tǒng)計(jì)人數(shù)
order_diff_i2 = order_diff_i1.reset_index().groupby('date').agg({'date':'count'})
order_diff_i2.columns =['count']
# 重置索引和強(qiáng)制轉(zhuǎn)換日期天數(shù)目錄為整型
data = order_diff_i2.reset_index()

# 畫圖激率,因?yàn)閎ar畫圖在matplot呈現(xiàn)不直觀乒躺,使用折線圖
y = data['count']
x1 = list(data.date.astype(int))
plt.plot(x1, y)
plt.title('用戶購買周期')
plt.xlabel('天數(shù)')
plt.ylabel('人數(shù)')
plt.legend()
42.PNG
  • 訂單周期呈指數(shù)分布
  • 用戶的平均購買周期是68天
  • 絕大部分用戶的購買周期都低于100天

7)用戶生命周期分布,第一次購買和最后一次購買的差值

# 用戶生命周期分布
user_l1 = df.groupby('user_id').agg({'date':[np.max, np.min]}).reset_index()
user_l1.columns = ['user_id', 'max_date', 'min_date']
# 時(shí)間格式轉(zhuǎn)為數(shù)字類型
user_l1['life'] = (user_l1['max_date'] - user_l1['min_date']) / np.timedelta64(1,'D')
user_l1['life'].describe()
# count    23570.000000
# mean       134.871956
# std        180.574109
# min          0.000000
# 25%          0.000000
# 50%          0.000000
# 75%        294.000000
# max        544.000000
# Name: life, dtype: float64
# 生命周期的均值為134,中位數(shù)為0

user_l1[user_l1['life'] >0 ].describe()
#   user_id life
# count 11516.000000    11516.000000
# mean  11718.596301    276.044807
# std   6822.464439 166.633990
# min   3.000000    1.000000
# 25%   5747.750000 117.000000
# 50%   11778.000000    302.000000
# 75%   17632.500000    429.000000
# max   23570.000000    544.000000
# 過濾生命周期為0 的數(shù)據(jù)后讳推,平均購買周期為276天银觅,中位數(shù)302

# 列表生成周期的分布標(biāo)簽究驴,切割周期數(shù)據(jù)后再分組統(tǒng)計(jì)
ls = [i for i in range(0, int(user_l1.life.max()+10),10)]
# 填充缺失值為最小值
user_l1['lf_label'] = pd.cut(user_l1['life'], bins=ls, labels=ls[1:]).fillna(10)
# 分組統(tǒng)計(jì)
user_l2 = user_l1.groupby('lf_label').agg({'user_id':'count'}).reset_index()

# 周期的目錄格式轉(zhuǎn)為數(shù)字格式洒忧,方便畫圖統(tǒng)計(jì)
user_l2['lf_label'] = user_l2.lf_label.astype(int)
# 畫圖統(tǒng)計(jì)
plt.plot(user_l2['lf_label'], user_l2['user_id'])
plt.xlabel('天數(shù)')
plt.ylabel('人數(shù)')
plt.title('用戶生命周期')
plt.legend()
43.PNG
  • 受只購買一次的用戶影響較大万皿,過濾生命周期為0 的數(shù)據(jù)后,平均購買周期為276天芝雪,中位數(shù)302
  • 用戶人均生命周期134天惩系,中位數(shù)僅為0天
# 篩選用戶生命周期大于1次的數(shù)據(jù)
user_l3 = user_l2[user_l2['lf_label']>10]

plt.plot(user_l3['lf_label'], user_l3['user_id'])
plt.xlabel('天數(shù)')
plt.ylabel('人數(shù)')
plt.title('用戶生命周期')
plt.legend()
44.PNG

5. 復(fù)購率和回購率
復(fù)購率:自然月內(nèi)堡牡,購買多次的用戶占比(即晤柄,購買了兩次以上)
回購率:在本周期內(nèi)購買了且下個(gè)周期也購買了的用戶占本周期總用戶的比例芥颈,曾經(jīng)購買過的用戶在某一時(shí)期的再次購買的占比(可能是在三個(gè)月內(nèi))

1)回購率計(jì)算

# 回購率計(jì)算
df_um = pd.pivot_table(df, values='money', index='user_id', columns='month', aggfunc='count')
df_um.head()
45.PNG

回購率函數(shù)的定義:
本月有購買且下個(gè)月也有購買時(shí),則為回購:1
本月有購買下個(gè)月沒有購買盾计,未回購:0
本月沒有購買應(yīng)為空值:np.nan署辉,這樣計(jì)算時(shí)count不會(huì)計(jì)算在內(nèi)
最后一個(gè)月的回購應(yīng)為np.nan

# 是否回購的判斷
def huigou(data):
    status = []
    for i in range(len(data)-1):
        if data[i] >= 1:
            if data[i+1] >= 1:
                status.append(1)
            else:
                status.append(0)
        else:
            status.append(np.nan)
    status.append(np.nan)
    return status

df_um1 = df_um.apply(lambda x :huigou(x), axis=1)

# 每月的回購率
# df_um1.sum() 每月回購人數(shù)統(tǒng)計(jì)
# df_um1.count() 每月購買總?cè)藬?shù)統(tǒng)計(jì)
hg = df_um1.sum()/df_um1.count()
# 重置索引&重命名列
hg1 = hg.reset_index()
hg1.columns = ['month','hg_rate']
hg1
46.PNG
# 回購率曲線繪制
import matplotlib.pyplot as plt
%matplotlib inline
plt.rcParams['font.sans-serif'] = 'SimHei'
plt.rcParams['axes.unicode_minus'] =False

plt.plot(hg1['month'], hg1['hg_rate'])
plt.ylabel('回購率')
plt.title('回購曲線')
plt.legend()
47.PNG

2)復(fù)購率計(jì)算

# 每月購買的人數(shù):df_um.count()
# 每月復(fù)購的人數(shù):df_um.applymap(lambda x : 1 if x>1 else 0).sum()
df_fg = df_um.applymap(lambda x : 1 if x>1 else 0).sum() / df_um.count()
# 索引重置&列重命名
df_fg1 = df_fg.reset_index()
df_fg1.columns = ['month', 'fg_rate']

plt.plot(df_fg1['month'], df_fg1['fg_rate'])
plt.ylabel('復(fù)購率')
plt.title('復(fù)購率曲線')
plt.legend()
48.PNG

小結(jié):

  • 回購率穩(wěn)定在30%左右炫乓,前三個(gè)月有大量新用戶涌入,導(dǎo)致回購率較低
  • 復(fù)購率穩(wěn)定在20%左右

四创橄、總結(jié)

  1. 用戶消費(fèi)趨勢分析
  • 前三個(gè)月有大量的新用戶涌入妥畏,消費(fèi)金額醉蚁、產(chǎn)品消費(fèi)數(shù)量
    网棍、消費(fèi)人數(shù)滥玷、訂單量均達(dá)到最高峰惑畴,后續(xù)每個(gè)月較為穩(wěn)定且呈輕微下降趨勢
  • 平均消費(fèi)金額呈波動(dòng)上升在11月達(dá)到頂峰后如贷,趨于波動(dòng)下降倒得,整體差異不大霞掺,在33-41之間
  • 平均訂單數(shù)在前三月從1.1上升到1.3菩彬,后續(xù)趨于穩(wěn)定在1.3-1.4區(qū)間內(nèi)
  1. 用戶個(gè)體消費(fèi)
  • 個(gè)別用戶購買了大量的產(chǎn)品骗灶,拉高了平均消費(fèi)金額耙旦,絕大部分的用戶購買金額在200以下免都,有12位用戶累計(jì)購金額大于4000绕娘;
  • 絕大部分的用戶只消費(fèi)了一次
  • 用戶累計(jì)消費(fèi)金額曲線看出险领,50%的用戶僅貢獻(xiàn)10%的消費(fèi)金額挨下,15%的用戶貢獻(xiàn)了60%的消費(fèi)金額复颈,符合二八法則
  1. 用戶消費(fèi)行為
  • 首購和最后一次購買時(shí)間集中在前三個(gè)月,說明很多用戶購買一次后就不買了机杜,而且用戶最后一次的購買時(shí)間在隨時(shí)間上升椒拗,消費(fèi)呈現(xiàn)流失狀態(tài)
  • 新老客戶看蚀苛,有一半的用戶僅消費(fèi)一次堵未;每月新客查看渗蟹,1月的新客占比達(dá)到90%以上雌芽,后續(xù)有所下降,3月后開始維持在81%左右
  • RFM模型看屉佳,在8種客戶中忘古,重要價(jià)值客戶的消費(fèi)頻次和消費(fèi)金額最高髓堪,人數(shù)排在第二位
  • 用戶分布情況來看干旁,新用戶從第4月份以后沒有新增争群;活躍用戶有所下降换薄;回流用戶數(shù)量趨于穩(wěn)定轻要,每月1000多冲泥。流失/不活躍用戶志秃,數(shù)量非常多浮还,基本上每月都在20000以上碑定。
  • 用戶購買周期方面延刘,用戶的平均購買周期是68天碘赖,絕大部分用戶的購買周期都低于100天
  • 用戶生命周期方面播掷,受只購買一次的用戶影響較大歧匈,排除這部分后件炉,平均購買周期為276天斟冕,中位數(shù)302
  1. 復(fù)購率和回購率方面,復(fù)購率穩(wěn)定在20%左右秀撇,回購率穩(wěn)定在30%左右捌袜,前3個(gè)月因?yàn)橛写罅啃掠脩粲咳耄@批用戶只購買了一次适肠,所以導(dǎo)致復(fù)購率和回購率都比較低。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末逛揩,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子逞泄,更是在濱河造成了極大的恐慌喷众,老刑警劉巖到千,帶你破解...
    沈念sama閱讀 218,682評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件膀息,死亡現(xiàn)場離奇詭異履婉,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)已烤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門妓羊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來胯究,“玉大人蘸泻,你說我怎么就攤上這事世曾。” “怎么了娇昙?”我有些...
    開封第一講書人閱讀 165,083評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵剥哑,是天一觀的道長。 經(jīng)常有香客問我淹父,道長株婴,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,763評(píng)論 1 295
  • 正文 為了忘掉前任暑认,我火速辦了婚禮困介,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘蘸际。我一直安慰自己座哩,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,785評(píng)論 6 392
  • 文/花漫 我一把揭開白布捡鱼。 她就那樣靜靜地躺著八回,像睡著了一般酷愧。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上缠诅,一...
    開封第一講書人閱讀 51,624評(píng)論 1 305
  • 那天溶浴,我揣著相機(jī)與錄音,去河邊找鬼管引。 笑死士败,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的褥伴。 我是一名探鬼主播谅将,決...
    沈念sama閱讀 40,358評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼重慢!你這毒婦竟也來了饥臂?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,261評(píng)論 0 276
  • 序言:老撾萬榮一對情侶失蹤似踱,失蹤者是張志新(化名)和其女友劉穎隅熙,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體核芽,經(jīng)...
    沈念sama閱讀 45,722評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡囚戚,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了轧简。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片驰坊。...
    茶點(diǎn)故事閱讀 40,030評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖哮独,靈堂內(nèi)的尸體忽然破棺而出拳芙,到底是詐尸還是另有隱情,我是刑警寧澤皮璧,帶...
    沈念sama閱讀 35,737評(píng)論 5 346
  • 正文 年R本政府宣布态鳖,位于F島的核電站,受9級(jí)特大地震影響恶导,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜浸须,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,360評(píng)論 3 330
  • 文/蒙蒙 一惨寿、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧删窒,春花似錦裂垦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春晕换,著一層夾襖步出監(jiān)牢的瞬間午乓,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評(píng)論 1 270
  • 我被黑心中介騙來泰國打工闸准, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留益愈,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,237評(píng)論 3 371
  • 正文 我出身青樓夷家,卻偏偏與公主長得像蒸其,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子库快,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,976評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 時(shí)間:2021/1/11-2021/1/18 下班后時(shí)間 學(xué)習(xí)內(nèi)容:第四階段可視化 第四章節(jié)案例 心得體會(huì): 1....
    anti醬閱讀 935評(píng)論 0 10
  • 目錄 分析目標(biāo) 分析過程 總結(jié)建議 一摸袁、分析目標(biāo) 本次分析報(bào)告的數(shù)據(jù)來源與這家單車網(wǎng)站上的用戶消費(fèi)記錄,通過分析用...
    我就是那個(gè)無敵大長腿閱讀 430評(píng)論 0 2
  • 單車銷售可視化案例總結(jié)老師指路->http://www.reibang.com/u/1f32f227da5f使用...
    Elena_fan閱讀 1,880評(píng)論 0 2
  • 這是一份用戶消費(fèi)行為的分析報(bào)告 1.進(jìn)行用戶消費(fèi)趨勢的分析(按月) 每月的消費(fèi)總金額 每月的消費(fèi)次數(shù) 每月的產(chǎn)品購...
    ohni_閱讀 1,315評(píng)論 0 0
  • 一义屏、項(xiàng)目介紹 CDNOW是一家網(wǎng)上唱片公司靠汁,通過18個(gè)月的用戶消費(fèi)記錄,深入分析用戶消費(fèi)行為湿蛔,建立RFM模型膀曾,進(jìn)行...
    SongSir1閱讀 1,381評(píng)論 0 8