用戶消費信息分析案例練習
1 人贊了文章
本文就某產品兩個月的消費記錄,進行分析。
本次數據包含兩張表:商品消費信息表,用戶信息表。主要從以下幾個維度進行:
使用工具:python
正文
導入相關庫
#導入相關庫import datetimeimport pandas as pdimport numpy as npimport matplotlib.pyplot as pltplt.style.use(ggplot)
讀取excel訂單數據
#讀取excel訂單數據fileName = order.xlsxxls = pd.ExcelFile(fileName)df_o = xls.parse(Sheet1)
讀取csv用戶數據
#讀取csv用戶數據columns = [user_id,sex,birthday]df_u = pd.read_csv(user_info_utf.csv,names = columns,sep = ,)
查看數據
訂單表各欄位含義
orderID: 商品id
userID :用戶id
ispaid :是否購買商品
price :成交金額
paidtime:購買時間
用戶表各欄位含義
user_id : 用戶id
sex : 性別
birthday: 生日
數據清洗
首先對訂單數據進行清洗
df_o.info()
篩選出已支付並且購買時間不為空的值
#篩選出已支付並且購買時間不為空的值df_o = df_o[(df_o[ispaid] == 已支付) & (df_o[paidtime].notnull())]
對日期標準化,改為年月日形式
#對日期標準化,改為年月日形式df_o[order_dt] = df_o[paidtime].apply(lambda x:x.date())
更改日期格式
#更改日期格式df_o[order_dt]=pd.to_datetime(df_o.order_dt,format=%Y-%m-%d)
將數據按照每天用戶購買數分組
#將數據按照每天用戶購買數分組df_c = df_o.groupby([order_dt,userID]).orderID.count().reset_index()df_p = df_o.groupby([order_dt,userID]).price.sum().reset_index()df_c[price] = df_p.price
更改列名
#更改列名columns = [order_dt,user_id,order_products,order_amount]df_c.columns = columns
算出時間相對應的星期,並算出是該年的第幾周(這裡使用的方法是以完整的7天為一周,不足7天不算,所以與實際可能存在1周的偏差)
#算出時間相對應的星期,並算出是第幾周df_c[weekday] = df_c.order_dt.apply(lambda x:x.weekday())df_c[weeks] = df_c.order_dt.apply(lambda x:x.strftime("%W"))
處理後數據信息
df_c.info()
處理後表
df_c.head()
對用戶數據清洗
df_u.info()
將生日轉換為日期格式,並按照訂單購買的最後一天計算年齡
#將生日轉換為日期格式,並按照訂單購買的最後一天計算年齡df_u[birthday] = pd.to_datetime(df_u.birthday,format=%Y/%m/%d,errors=coerce)df_u[age] = df_o.order_dt.values.astype(datetime64[Y]).max()-df_u.birthday.values.astype(datetime64[Y])df_u[age] = df_u[age]/np.timedelta64(1,Y)
為了使年齡更加準確,這裡選取年齡為18-80歲的數據
#為了使年齡更加準確,這裡選取18-80歲df_u = df_u[(df_u[age] > 17) & (df_u[age] < 81) | (df_u[age].isnull())]
處理後數據信息
df_u.info()
合併數據集
#合併數據集df = pd.merge(df_c,df_u,how = left,left_on = user_id,right_on = user_id)df.tail()
由於5月2日只有一項紀錄,這裡去掉該項
df = df[:-1]
查看最終數據
df.info()
描述統計
df.describe()
- 大部分訂單只是消費了少量商品(平均3.7),有極值干擾
- 用戶的消費金額同樣受極值干擾
用戶消費趨勢(按周)
每周消費總金額
按每周分類
#按每周分類grouped_weeks = df.groupby(weeks)
繪製折線圖
plt.figure(figsize=(10,6))plt.plot(grouped_weeks.order_amount.sum())plt.title(每周消費總金額)
從圖像可知,消費金額在前幾周增長迅速,在第13周有所下降,隨後繼續增長並在第16周達到最高峰,又在最後一周下跌
每周消費次數
plt.figure(figsize=(10,6))plt.plot(grouped_weeks.user_id.count())plt.title(每周消費次數)
由上圖可知,前四周消費訂單數成上升趨勢,第五周開始下降,到最後一周僅剩9500單
每周產品購買量
plt.figure(figsize=(10,6))plt.plot(grouped_weeks.order_products.sum())plt.title(每周產品購買量)
由上圖可以看出,每周產品購買量整體趨勢與消費金額相似,結合每周訂單數可以看出,該商品在後期存在用戶大量購買的情況。另外在第16周總消費金額大於第13周,然而消費總商品數卻相反,說明該商品有漲價行為
每周消費人數
plt.figure(figsize=(10,6))plt.plot(grouped_weeks.user_id.apply(lambda x:x.drop_duplicates().count()))plt.title(每周消費人數)
每周消費人數低於消費出三個月,但差異不大
將該商品消費金額兩次下跌,單獨分析
#繪製第13、17周以及總消費折線圖fig=plt.figure(figsize=(7,14))ax1=fig.add_subplot(311)ax1.plot(df[df[weeks]==13].groupby(order_dt).order_amount.sum(),color=b,label=第13周記錄)plt.legend(loc=best)ax2=fig.add_subplot(312)ax2.plot(df[df[weeks]==17].groupby(order_dt).order_amount.sum(),color=y,label=第17周記錄)plt.legend(loc=best)ax3=fig.add_subplot(313)ax3.plot(df.groupby(weekday).order_amount.sum(),color=r,label=總記錄)plt.legend(loc=best)
從消費金額每日趨勢圖可以看出,該商品一般情況下在周二至周四達到高峰,隨著節假日的到來,有所下降,在周六達到低估,在周日回有所回升,考慮為工作做準備。而第13周和第17周都在周日不增反減,考慮是受清明節與五一節的影響。所以該商品銷量受節假日影響較大。
用戶個體消費分析
用戶消費金額,消費次數的描述統計
按用戶分組,並查看描述統計
grouped_user = df.groupby(user_id)grouped_user.sum().describe()
- 用戶平均購買了5件商品,但中位數只有1說明小部分用戶購買了大量的商品
- 用戶平均消費3700元,中位數有737,判斷同上,有極值干擾
用戶消費金額和消費的散點圖
這裡勁量避免極值干擾,選取消費金額小於400000,商品數少於2000的數據
grouped_user.sum().query("order_amount<400000").plot.scatter(x=order_amount,y=order_products,figsize=(10,6))plt.title(用戶消費金額和消費的散點圖)
可以看出,大部分用戶購買了少量產品
用戶累計新消費金額佔比(百分之多少的用戶佔了百分之多少的消費)
user_cumsum = grouped_user.sum().query(order_amount<400000).sort_values(order_amount).apply(lambda x:x.cumsum()/x.sum())user_cumsum.reset_index().order_amount.plot(figsize=(10,6))plt.title(用戶累計新消費金額佔比)
按用戶消費金額進行升序排列,由圖可知,50%的用戶僅貢獻了25%的消費額度。而排名前一萬的用戶就貢獻了40%的消費額。
用戶消費行為
用戶第一次消費(首購)
grouped_user.order_dt.min().value_counts().plot(figsize=(16,8))
用戶第一次購買在每個周六都會有所下降,並且整體呈下降趨勢,說明新用戶在減少
用戶最後一次消費
grouped_user.order_dt.max().value_counts().plot(figsize=(16,8))plt.title(用戶最後一次消費)
用戶最後一次購買同樣在每個周六都會有所下降(考慮周六消費人數較少),並且整體有略微上升的趨勢,說明老用戶在流失
多少用戶僅消費一次
user_life = grouped_user.order_dt.agg([max,min])user_life.head()
(user_life[min] == user_life[max]).value_counts().plot.pie(figsize=(10,8),labels=[僅消費一次的客戶,消費一次以上的客戶])plt.title(多少用戶僅消費一次)
70%以上的用戶僅消費了一次
用戶分層
RFM
數據透視
rfm = df.pivot_table(index = user_id, values = [order_products,order_amount,order_dt], aggfunc={order_dt:max, order_amount:sum, order_products:sum })
這裡時間以最後一次消費為標準,對RMF模型進行處理。按照每個指標與平均數的對比,將用戶分為8個標籤:
- 重要價值客戶
- 重要保持客戶
- 重要挽留客戶
- 重要發展客戶
- 一般保持客戶
- 一般挽留客戶
- 一般發展客戶
#計算最近一次消費時間rfm[R] = -(rfm[order_dt]-rfm[order_dt].max())/np.timedelta64(1,D)#更改列名rfm.rename(columns = {order_products:F,order_amount:M},inplace = True)#定義轉換函數def rfm_func(x): level = x.apply(lambda x:1 if x>0 else 0) label = level.R + level.F + level.M d = { 111:重要價值客戶, 011:重要保持客戶, 101:重要挽留客戶, 001:重要發展客戶, 010:一般保持客戶, 100:一般挽留客戶, 000:一般發展客戶 } result = d[label] return resultrfm[label] = rfm[[R,F,M]].apply(lambda x:x-x.mean()).apply(rfm_func,axis=1)#篩選數據rfm = rfm[(rfm[F]<2000) & (rfm[M]<400000)]
按類型對金額統計
rfm.groupby(label).sum()
按類型對購買人數統計
rfm.groupby(label).count()
繪製散點圖
fig=plt.figure(figsize=(16,8))ax1=fig.add_subplot(111)ax1.scatter(rfm.loc[rfm.label == 重要價值客戶].F,rfm.loc[rfm.label == 重要價值客戶].R,label=重要價值客戶,color=g,alpha=.5)ax1.scatter(rfm.loc[rfm.label == 重要保持客戶].F,rfm.loc[rfm.label == 重要保持客戶].R,label=重要保持客戶,color=b,alpha=.5)ax1.scatter(rfm.loc[rfm.label == 重要挽留客戶].F,rfm.loc[rfm.label == 重要挽留客戶].R,label=重要挽留客戶,color=r,alpha=.5)ax1.scatter(rfm.loc[rfm.label == 重要發展客戶].F,rfm.loc[rfm.label == 重要發展客戶].R,label=重要發展客戶,color=k,alpha=.5)ax1.scatter(rfm.loc[rfm.label == 一般價值客戶].F,rfm.loc[rfm.label == 一般價值客戶].R,label=一般價值客戶,color=m,alpha=.5)ax1.scatter(rfm.loc[rfm.label == 一般保持客戶].F,rfm.loc[rfm.label == 一般保持客戶].R,label=一般保持客戶,color=y,alpha=.5)ax1.scatter(rfm.loc[rfm.label == 一般挽留客戶].F,rfm.loc[rfm.label == 一般挽留客戶].R,label=一般挽留客戶,color=c,alpha=.5)ax1.scatter(rfm.loc[rfm.label == 一般發展客戶].F,rfm.loc[rfm.label == 一般發展客戶].R,label=一般發展客戶,color=w,alpha=.5)plt.xlabel(F)plt.ylabel(R)plt.legend(loc=best)
這裡結合圖表發現一般發展客戶,一般挽留客戶居然佔據了最高的消費金額,這一方面是由於數據時間段太短,另一方面是由於這兩個指標擁有大量的人群。此外RMF模型的劃分標準應該以業務為準。
男女消費對比
這裡注意,計算人數用去重,消費總金額用戶分組
#這裡注意,計算人數用去重,消費總金額用戶分組df_dup = df.drop_duplicates(subset=user_id,keep=first)
繪製條形圖
fig=plt.figure(figsize=(10,6))ax1=fig.add_subplot(131)ax1.bar(df_dup.sex.value_counts().index,df_dup.sex.value_counts().values)plt.title(男女人數比)ax2=fig.add_subplot(132)ax2.bar(df.groupby(sex).order_amount.sum().index,df.groupby(sex).order_amount.sum().values)plt.title(男女消費比)ax3=fig.add_subplot(133)ax3.bar((df.groupby(sex).order_amount.sum()/df_dup.sex.value_counts()).index,(df.groupby(sex).order_amount.sum()/df_dup.sex.value_counts()).values)plt.title(男女人均消費比)
從圖中可以看出,雖然男士比女士人數多,但是女士的評分消費水平更大
年齡段消費對比
篩選出年齡不為空的數據
df_age = df[df[age].notnull()]
將年齡分組
bins = [0,25,35,45,55,65,100]level = [0-25,25-35,35-45,45-55,55-65,65以上]df_age[level] = pd.cut(df_age[age],bins = bins,labels = level)df_age.head()
按用戶去重
df_age_dup = df_age.drop_duplicates(subset=user_id,keep=first)
繪製條形圖
fig=plt.figure(figsize=(10,6))ax1=fig.add_subplot(121)ax1.bar(df_age.groupby(level).order_amount.sum().index,df_age.groupby(level).order_amount.sum().values)plt.title(各年齡段人數比)ax2=fig.add_subplot(122)ax2.bar(df_age_dup.level.value_counts().index,df_age_dup.level.value_counts().values)plt.title(各年齡段消費比)
由上圖可知,25-35歲無論是消費人數還是消費金額都遙遙領先,是該商品主要目標客戶。
推薦閱讀:
※全國霧霾大數據,哪裡才是桃花源?
※hive入門第二章-增刪改查
※可視化開腦洞期刊(一)
※重做紅樓夢的數據分析-判斷前80回後40回是否一個人寫的
※誰動了你的文件 -- 使用「透視表」分析文件訪問日誌
TAG:數據分析 |