單車案例分析

目錄

  • 分析目標
  • 分析過程
  • 總結建議

一、分析目標

本次分析報告的數(shù)據(jù)來源與這家單車網站上的用戶消費記錄,通過分析用戶消費行為,建立RFM模型,分析復購率、回購率等關鍵指標,對該產品的線上消費數(shù)據(jù)進行分析并提出有價值的建議。

二、分析思路與過程

分析思路

分析過程

0、數(shù)據(jù)集的觀察與清洗

(1)導入數(shù)據(jù)包

import pandas as pd  
import numpy as np

(2)導入數(shù)據(jù)集

columns=['user_id','order_dt','order_products','order_amount']
df=pd.read_table('D:\\Users\\yuan\\Desktop\\bicycle_master.txt',names=columns, sep='\s+')

(3)數(shù)據(jù)集清洗

查看數(shù)據(jù)是否有缺失

df.info()


大部分訂單只消費了少量商品(平均2.4),有一定值干擾
用戶的消費金額比較穩(wěn)定,平均消費35元,中位數(shù)在35元,有一定極值的干擾

df['order_dt']=pd.to_datetime(df.order_dt,format="%Y%m%d")
df['month']=df.order_dt.values.astype('datetime64[M]')

對時間進行解析,一開始默認的格式是 int64的,可以用 df.info() 來查看,默認會是 datetime64[ns] 類型,后面中括號表示 時間間隔是 ns
下面是對 order_dt 列(取values),轉換類型為datetime64[M],默認就會是每月的第一天了,同理設置為[Y]就是每年的1月1日,然后生成新的一列 month

1、進行用戶消費趨勢的分析(按月)

(1)每月的消費總金額

grouped_month=df.groupby('month')
order_month_amount=grouped_month.order_amount.sum()
order_month_amount.head()

(2)每月的消費次數(shù)

(3)每月的產品購買量

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':'消費金額', 'user_id': '消費次數(shù)', 'order_products': '產品購買量'}, inplace=True)
grouped_month_info

(4)每月的消費人數(shù)

grouped_month_info['消費人次'] = grouped_month['user_id'].unique().map(len)
grouped_month_info = grouped_month_info.reset_index()
grouped_month_info['month'] = grouped_month_info['month'].astype(str)

grouped_month_info['month'] = grouped_month_info['month'].astype(str)
grouped_month_info.to_excel('D:\\Users\\yuan\\Desktop\\臨時表\月銷售額、銷售次數(shù)、產品購買量、消費人數(shù).xlsx')

由上圖可知,消費金額在前三個月達到最高峰,后續(xù)消費較為穩(wěn)定,有輕微下降趨勢


由上圖可知,產品購買量在前三個月達到最高峰,后續(xù)消費較為穩(wěn)定,有輕微下降趨勢


前三個月消費訂單人數(shù)在10000筆左右,后續(xù)月份的平均消費人數(shù)則在2500人
去重的方法有多種,這里也可以使用數(shù)據(jù)庫思想,df.groupby(['month','user_id']).count().reset_index()
每月消費人數(shù)低于每月消費次數(shù),但差異不大
前三個月每月的消費人數(shù)在8000-10000之間,后續(xù)月份,平均消費人數(shù)在2000不到

# 上面進行的匯總分析,其實可以用數(shù)據(jù)透視的方法更快實現(xiàn),一次性求出結果
df.pivot_table(index='month',
              values=['order_products','order_amount','user_id'],
              aggfunc={'order_products':'sum',
                      'order_amount':'sum',
                      'user_id':'count'}).head()
  • 每月用戶平均消費金額的趨勢
amount=grouped_month.order_amount.sum()
num=df.groupby('month').user_id.apply(lambda x:len(x.drop_duplicates()))
avg_amount=amount/num
  • 每月用戶平均消費次數(shù)的趨勢
times=grouped_month.user_id.count()
num=df.groupby('month').user_id.apply(lambda x:len(x.drop_duplicates()))
avg_times=times/num

2.用戶個體消費分析

  • 用戶消費金額和消費次數(shù)的散點圖
  • 用戶消費金額的分布圖
  • 用戶消費次數(shù)的分布圖
  • 用戶累計消費金額占比(百分之多少的用戶占了百分之多少的消費額)

(1)用戶消費金額,消費次數(shù)的描述統(tǒng)計

grouped_user=df.groupby('user_id')

grouped_user.sum().describe()

用戶平均購買了7張,但是中位值只有3,說明小部分用戶購買了大量貨物
用戶平均消費106元,中位值有43,判斷同上,有極值干擾

grouped_user_info = grouped_user.sum()

grouped_user_info.to_excel('D:\\Users\\yuan\\Desktop\\臨時表\用戶個體消費行為分析.xlsx')
grouped_user_info
grouped_user_sum_order_amount = grouped_user.sum().order_amount
grouped_user_sum_order_amount_lst = [i for i in range(0,int(grouped_user_sum_order_amount.max())+1,50)]

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:])
pd.cut(grouped_user_sum_order_amount,bins=100)
grouped_user_sum_order_amount.to_excel('D:\\Users\\yuan\\Desktop\\臨時表\消費金額分布直方圖.xlsx')

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

使用切比雪夫定理過濾掉異常值,因為切比雪夫定理說明,95%的數(shù)據(jù)都分布在5個標準差之內,剩下5%的極值就不要了

order_amount (mean = 106 ,std = 241) mean+5std = 1311

grouped_user.sum().sort_values('order_amount').sum()
grouped_user.sum().sort_values('order_amount').cumsum()/grouped_user.sum().sort_values('order_amount').sum()
# cumsum 是求累加值
user_cumsum=grouped_user.sum().sort_values('order_amount').apply(lambda x:x.cumsum()/x.sum())
# 這里 reset_index() 是為了得到一個自然數(shù)的行標簽,表示的就是人數(shù),下面的圖就可以看出來多少個少占多少百分比
user_cumsum
user_cumsum.reset_index().order_amount.to_excel('D:\\Users\\yuan\\Desktop\\臨時表\累積銷售.xlsx')

按照用戶消費金額進行升序排序,由圖可以知道50%的用戶僅貢獻了11%的消費額度,而排名前5000的用戶就貢獻了60%的消費額度

3.用戶消費行為

(1)用戶第一次消費(首購)

grouped_user_min = grouped_user.min().order_dt.value_counts().reset_index().rename(columns={'index':'first_date'})
grouped_user_min['first_date'] =grouped_user_min['first_date'].astype(str)
grouped_user_min.to_excel('D:\\Users\\yuan\\Desktop\\臨時表\用戶首購.xlsx')
grouped_user_max = grouped_user.max().order_dt.value_counts().reset_index().rename(columns={'index':'last_date'})

grouped_user_max['last_date'] =grouped_user_max['last_date'].astype(str)

grouped_user_max.to_excel(r'.\臨時表\用戶最后一次購買.xlsx')

斷崖式下跌很正常:可以理解用戶流失比例基本一致,一開始用戶迅猛增長數(shù)量比較多流失的也比較多,后面沒有用戶
用戶最后一次購買的分布比第一次分布廣
大部分最后一次購買,集中在前三個月,說明很多用戶購買了一次后就不再進行購買
隨著時間的遞增,最后一次購買數(shù)量也在遞增,消費呈現(xiàn)流失上升的狀況(這也是正常,隨著時間的增長,可能運營每跟上,或者用戶忠誠度下降了)

(3)新老客戶消費比

# 得到第一次和最后yc次消費情況,如果 min、max 日期相同,說明只消費了一次
user_life=grouped_user.order_dt.agg(['min','max'])
(user_life['min']==user_life['max'])
# 統(tǒng)計只消費了一次的用戶
(user_life['min']==user_life['max']).value_counts()

有一半的用戶,只消費了一次

(4) 每月新客占比

  #按月分組下的userid分組,求每月的最早購買日期和最晚消費日期
grouped_um = df.groupby(['month','user_id']).order_dt.agg(["min","max"])  
  # 新增列 True 為 新用戶
grouped_um["new"] = (grouped_um["min"] == grouped_um["max"] )           
# 再次按month分組,計算新用戶占比
user_life_month_pct=user_life_month.groupby('month').is_new.apply(lambda x:x.value_counts()/x.count()).reset_index()

(5)用戶分層

# 畫 RFM,先對原始數(shù)據(jù)進行透視
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()
-(rfm.order_dt - rfm.order_dt.max()) / np.timedelta64(1,'D')
# 得到最近一次消費,一般是計算 today 距離最近一次消費,這里因為時間太久遠,就隨便用的max值
# 數(shù)值越大就越久遠,分子得到的是一些天數(shù)類似 545 days(因為是時間格式相減),處以一個單位,就不會有單位了只留下數(shù)值
rfm['R']= (rfm.order_dt - rfm.order_dt.max())/np.timedelta64(1,'D')
# 重命名,也就是 R:最后一次消費距今天數(shù),F(xiàn):消費總金額 ,M:消費總產品數(shù)
# R :消費時間  F:消費金額  M:消費頻次
rfm.rename(columns={'order_products':"F",'order_amount':'M'},inplace=True)
rfm[['R','F','M']].apply(lambda x:x-x.mean())
def rfm_func(x):
    level=x.apply(lambda x:'1' if x>=0 else '0')
    # level 的類型是 series,index 是 R、F、M
#     print(type(level))
#     print(level.index)
    label=level.R + level.F + level.M
    d={
        # R 為1 表示離均值較遠即時間很久,F(xiàn)為1 表示 消費金額比較多,M 為1 表示消費頻次比較多,所以是重要價值客戶
        '111':'重要價值客戶',
        '011':'重要保持客戶',
        '101':'重要發(fā)展客戶',
        '001':'重要挽留客戶',
        '110':'一般價值客戶',
        '010':'一般保持客戶',
        '100':'一般發(fā)展客戶',
        '000':'一般挽留客戶',
    }
    result=d[label]
    return result
# 注意這里是要一行行的傳遞進來,所以 axis=1,傳遞一行得到一個 111,然后匹配返回一個值
rfm['label']=rfm[['R','F','M']].apply(lambda x:x-x.mean()).apply(rfm_func,axis=1)
rfm.loc[rfm.label=='重要價值客戶','color']='重要價值客戶'
rfm.loc[~(rfm.label=='重要價值客戶'),'color']='非重要價值客戶'
rfm
rfm.to_excel('D:\\Users\\yuan\\Desktop\\臨時表\RFM模型.xlsx')
rfm.groupby('label').sum()

從RFM 分層可知,大部分用戶是重要保持客戶,但是這是由于極值的影響,所以 RFM 的劃分標準應該以業(yè)務為準,也可以通過切比雪夫去除極值后求均值,并且 RFM 的各個劃分標準可以都不一樣
盡量用小部分的用戶覆蓋大部分的額度
不要為了數(shù)據(jù)好看劃分等級

(6)用戶生命周期

新客,活躍,回流,流失(一段時間不消費,或者不活躍)

# 數(shù)據(jù)透視, userid為索引,月為列,求每月的消費次數(shù),這里填充了
pivoted_counts=df.pivot_table(index='user_id',
                             columns='month',
                             values='order_dt',
                             aggfunc='count').fillna(0)
pivoted_counts.head()
# 轉變一下消費,有消費為1,沒有消費為0
df_purchase=pivoted_counts.applymap(lambda x:1 if x>0 else 0)
df_purchase.tail()
# 這里由于進行數(shù)據(jù)透視,填充了一些 null 值為0,而實際可能用戶在當月根本就沒有注冊,
#這樣會誤導第一次消費數(shù)據(jù)的統(tǒng)計,所以寫一個函數(shù)來處理
def active_status(data):
    status=[]
    # 數(shù)據(jù)一共有18個月份,每次輸入一行數(shù)據(jù),這樣進行逐月判斷
    for i in range(18):
        # 若本月沒有消費,上面處理過的結果
        if data[i]==0:
            if len(status)>0:
                if status[i-1]=='unreg':
                    status.append('unreg')
                else:
                    status.append('unactive')
            else:
                # 之前一個數(shù)據(jù)都沒有,就認為是未注冊
                status.append('unreg')
                
        # 若本月消費
        else:
            if len(status)==0:
                status.append('new')
            else:
                if status[i-1]=='unactive':
                    status.append('return')
                elif status[i-1]=='unreg':
                    status.append('new')
                else:
                    status.append('active')
    return status

若本月沒有消費,這里只是和上個月判斷是否注冊,有缺陷,可以判斷是否存在就可以了

  • 若之前是未注冊,則依舊為未注冊
  • 若之前有消費,則為流失/不活躍
  • 其他情況,為未注冊

若本月有消費

  • 若是第一次消費,則為新用戶
  • 如果之前有過消費,則上個月為不活躍,則為回流
  • 如果上個月為未注冊,則為新用戶
  • 初次之外,為活躍

return:回流

new:新客

unreg:未注冊

active:活躍

purchase_stats=df_purchase.apply(lambda x: pd.Series(active_status(x),index=df_purchase.columns),axis=1)
purchase_stats.head()
# 這里把未注冊的替換為空值,這樣 count 計算時不會計算到
# 得到每個月的用戶分布
purchase_stats_ct=purchase_stats.replace('unreg',np.NaN).apply(lambda x:pd.value_counts(x))
purchase_stats_ct
returnratee=purchase_stats_ct.apply(lambda x:x/x.sum(),axis=0)
returnratee
purchase_stats_ct_info = purchase_stats_ct.fillna(0).T
purchase_stats_ct_info
purchase_stats_ct_info.index = purchase_stats_ct_info.index.astype(str)

purchase_stats_ct_info.to_excel('D:\Users\yuan\Desktop\臨時表\用戶分層-新、活躍、流失、回流.xlsx')

# 求出所有用戶的占比
purchase_stats_ct_T = purchase_stats_ct.fillna(0).T.apply(lambda x:x/x.sum(),axis=1)
purchase_stats_ct_T
purchase_stats_ct_T / purchase_stats_ct_T.shift()
purchase_stats_ct_T.shift()

前三個月有大量新用戶涌入,新用戶占比很高,而后面幾個月不活躍用戶占比非常高,普遍在90%以上。
活躍用戶,持續(xù)消費的用戶,對應的是消費運營的質量。
回流用戶,之前不消費,本月才消費,對應的是喚回運營。
不活躍用戶,對應的是流失。

(6) 用戶購買周期(按訂單)

# 計算相鄰兩個訂單的時間間隔,shift 函數(shù)是對數(shù)據(jù)進行錯位,所有數(shù)據(jù)會往下平移一下,所以可以
order_diff=grouped_user.apply(lambda x:x.order_dt-x.order_dt.shift())
order_diff.head(10)
#描述性統(tǒng)計
order_diff.describe()
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:])
order_diff_info_hist = order_diff_info_hist.fillna(10)

order_diff_info_hist.to_excel('D:\Users\yuan\Desktop\臨時表\用戶購買周期時間差頻率直方圖.xlsx')



訂單周期呈指數(shù)分布
用戶的平均購買周期是68天
絕大部分用戶的購買周期都低于100天

(7)用戶生命周期(按第一次和最后一次消費)

#描述性統(tǒng)計
(user_life['max']-user_life['min']).describe()
user_life_info = ((user_life['max']-user_life['min'])/np.timedelta64(1,"D"))
user_life_lst = [i for i in range(0,int(user_life_info.max())+1,10)]
user_life_info_hist = pd.cut(user_life_info,bins=user_life_lst,labels=user_life_lst[1:])
user_life_info_hist
user_life_info_hist_2 = user_life_info_hist.fillna(10)
user_life_info_hist_2.to_excel('D:\\Users\\yuan\\Desktop\\臨時表\用戶生命周期頻率直方圖.xlsx')

用戶的生命周期受只購買一次的用戶影響比較厲害(可以排除)
用戶均消費134天,中位數(shù)僅0天

user_life["差值"]=(user_life["max"] - user_life["min"])/np.timedelta64(1,"D")
user_life.head(5)
user_life_info_hist.to_excel('D:\\Users\\yuan\\Desktop\\臨時表\用戶生命周期頻率直方圖(忽略一次購買).xlsx')

4.復購率和回購率分析

復購率
自然月內,購買多次的用戶占比(即,購買了兩次以上)
回購率
曾經購買過的用戶在某一時期的再次購買的占比(可能是在三個月內)

(1) 復購率

#消費次數(shù)
pivoted_counts.head(10)
# 區(qū)分一個,和一個以上的情況,以便于計算復購率,大于1為1,等于0 為0,等于1為0 
purchase_r=pivoted_counts.applymap(lambda x: 1 if x>1 else np.NaN if x==0 else 0)
purchase_r.head()
purchase_r_reshop = (purchase_r.sum()/purchase_r.count()).reset_index(name = 'reshop')
purchase_r_reshop
purchase_r_reshop['month'] = purchase_r_reshop['month'].astype(str)
purchase_r_reshop.to_excel('D:\\Users\\yuan\\Desktop\\臨時表\復購人數(shù)與總消費人數(shù)比例.xlsx')

復購率穩(wěn)定在20%所有,前一個月因為有大量新用戶涌入,而這批用戶只購買了一次,所以導致復購率降低

回購率

# 需要使用函數(shù)來判斷是否回購:當月消費過的用戶下個月也消費了叫做回購,這個定義可以改變
def purchase_back(data):
    '''判斷每一個月是否是回購,根據(jù)上個月是否購買來判斷,上個月消費下個月沒有購買就不是回購'''
    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個月補充NaN
    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()
purchase_b_backshop = purchase_b.sum()/purchase_b.count()
purchase_b_backshop.index
purchase_b_backshop.index = purchase_b_backshop.index.astype(str)
purchase_b_backshop.to_excel('D:\\Users\\yuan\\Desktop\\臨時表\回購率.xlsx')

三、總結建議

1、用戶消費趨勢(每月)方面,前3個月有大量新用戶涌入,消費金額、消費訂單數(shù)、產品購買量均達到高峰,后續(xù)每月較為穩(wěn)定。前3個月消費次數(shù)都在10000筆左右,后續(xù)月份的平均2500;前3個月產品購買量達到20000甚至以上,后續(xù)月份平均7000;前3個月消費人數(shù)在8000-10000之間,后續(xù)月份平均2000不到。
2、用戶個體消費方面,小部分用戶購買了大量的CD,拉高了平均消費金額。用戶消費金額集中在0100元,有大約17000名用戶。用戶購買量集中在05,有大約16000名用戶。50%的用戶僅貢獻了15%的消費額度,15%的用戶貢獻了60%的消費額度。大致符合二八法則。
3、用戶消費行為方面,首購和最后一次購買的時間,集中在前三個月,說明很多用戶購買了一次后就不再進行購買。而且最后一次購買的用戶數(shù)量也在隨時間遞增,消費呈現(xiàn)流失上升的狀況。
4、從整體消費記錄來看,有一半的用戶,只消費了一次。從每月新用戶占比來看,1997年1月新用戶占比高達90%以上,后續(xù)有所下降,1997年4月到1998年6月維持在81%左右,1998年6月以后無新用戶。
5、從RFM模型來看,在8種客戶中,重要保持客戶的消費頻次和消費金額最高,人數(shù)排在第二位;而一般發(fā)展客戶消費頻次和消費金額排第二位,人數(shù)卻是最多。
6、從用戶分層情況來看,新用戶從第4月份以后沒有新增;活躍用戶有所下降;回流用戶數(shù)量趨于穩(wěn)定,每月1000多。流失/不活躍用戶,數(shù)量非常多,基本上每月都在20000以上。
7、用戶購買周期方面,平均購買周期是68天,最小值0天,最大值533天。絕大部分用戶的購買周期都低于100天。
8、用戶生命周期方面,由于只購買一次的用戶(生命周期為0天)占了接近一半,排除這部分用戶的影響之后,用戶平均生命周期276天,中位數(shù)302天。
9、復購率和回購率方面,復購率穩(wěn)定在20%左右,回購率穩(wěn)定在30%左右,前3個月因為有大量新用戶涌入,而這批用戶只購買了一次,所以導致復購率和回購率都比較低。

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內容