In [1]:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
df=pd.read_csv("CDNOW_MASTER.CSV")
df.head()
Out[1]:
- ID:购买用户id
- DATE:用户购买日期
- NUM:用户购买数量
- TOTAL:用户购买总额
In [2]:
df.info()
In [3]:
df.describe()
Out[3]:
- 大部分订单只有1-3的销量,平均值为2.4,且存在一定极值干扰
- 用户消费金额比较稳定,平均数是36,中位数是25,存在一定极值干扰
In [4]:
df['DATE']=pd.to_datetime(df['DATE'],format='%Y%m%d')
df['month']=df.DATE.values.astype('datetime64[M]')
df
Out[4]:
1.进行用户消费趋势分析(按月)¶
- 每月的消费总金额
- 每月的消费次数
- 每月的产品购买量
- 每月的消费人数
In [5]:
grouped_month=df.groupby(by='month')
order_month_amount=grouped_month.TOTAL.sum()
order_month_amount.head()
Out[5]:
In [6]:
#可视化显示在页面
%matplotlib inline
#更改设计风格
plt.style.use('ggplot')
order_month_amount.plot()
Out[6]:
由上图可知,消费金额在前三个月达到最高峰,后续消费较为稳定,有轻微下降趋势
In [7]:
grouped_month.ID.count().plot()
Out[7]:
由上图可知,消费次数在前三个月达到最高峰,后续消费次数较为稳定,有轻微下降趋势
In [8]:
grouped_month.NUM.sum().plot()
Out[8]:
由上图可知,每月购买产品量在前三个月达到最高峰,后续购买量较为稳定,有轻微下降趋势
In [9]:
grouped_month.ID.apply(lambda x :len(set(x))).plot()
Out[9]:
由上图可知,每月消费人数在前三个月达到最高峰,每月消费人数较为稳定,有轻微下降趋势
2.用户个体消费分析¶
- 用户消费金额、消费次数的描述统计
- 用户消费金额和消费次数的散点图
- 用户消费金额的分布图
- 用户消费次数的分布图
- 用户累计消费金额占比
In [10]:
grouped_user=df.groupby('ID')
In [11]:
grouped_user.sum().describe()
Out[11]:
- 用户平均购买了7张CD,但中位值只有3,说明小部分用户购买大多数的CD
- 用户平均消费106元,中位值有43,判断同上,有极值干扰
In [12]:
grouped_user.sum().query('TOTAL<4000').plot.scatter(x='TOTAL',y='NUM')
Out[12]:
用户消费总金额集中在1500元以下,购买总CD数量集中在100张以下
In [13]:
grouped_user.sum().query('NUM<100').TOTAL.plot.hist(bins=20)
Out[13]:
大多数用户消费金额在250元以下
In [14]:
grouped_user.sum().query('NUM<100').NUM.plot.hist(bins=20)
Out[14]:
大多数用户购买CD数量在20张以下
In [15]:
user_cumsum=grouped_user.sum().sort_values('TOTAL').apply(lambda x :x.cumsum()/x.sum())
user_cumsum.reset_index().TOTAL.plot()
Out[15]:
按照用户消费金额进行升序排列,50%的用户仅贡献了15%的消费额度,消费总额排名前5000的贡献了60%的消费额度
3.用户消费行为¶
- 用户第一次消费(首购)
- 用户最后一次消费
- 新老客消费比
- 多数用户仅消费一次?
- 每月新老客占比?
- 用户分层
- RFM
- 新、老、活跃、回流、流失
- 用户购买周期(按订单)
- 用户消费周期描述
- 用户消费周期分布
- 用户生命周期(按照第一次&最后一次消费)
- 用户生命周期描述
- 用户生命周期分布
In [16]:
grouped_user.min().DATE.value_counts().plot()
Out[16]:
用户第一次购买分布,集中在前三个月。并且在2-11至2-25有一次剧烈波动,具体再分析
In [17]:
grouped_user.max().DATE.value_counts().plot()
Out[17]:
用户最后一次购买比第一次购买分布广,大部分最后一次购买集中在前三个月,说明很多用户第一次购买后不再进行购买,随着时间,最后一次购买数在增加,消费呈流失上升的状况。
In [18]:
user_life=grouped_user.DATE.agg(['min','max']).reset_index()
user_life.head()
Out[18]:
In [19]:
(user_life['min']==user_life['max']).value_counts()
Out[19]:
有一半用户, 就 消费了一次
In [20]:
user_life['regDate']=user_life['min'].values.astype('datetime64[M]')
user_life
Out[20]:
In [21]:
user_life_month=df.groupby(['month','ID']).count().reset_index()
In [22]:
user_life_month=user_life_month.merge(user_life,on='ID')
In [23]:
user_life_month
Out[23]:
In [24]:
user_life_month['isNew']=user_life_month.apply(lambda x:True if x.month==x.regDate else np.NaN,axis=1)
In [25]:
user_life_month_count=user_life_month.groupby('month').count().reset_index()
In [26]:
user_life_month_count
Out[26]:
In [27]:
user_life_month_count['isOld']=pd.DataFrame(user_life_month_count['ID']-user_life_month_count['isNew'])
user_life_month_count.drop(columns=['DATE','NUM','TOTAL','min','max','regDate'],inplace=True)
In [28]:
user_life_month_count.rename(columns={'ID':'all'},inplace=True)
In [29]:
user_life_month_count
Out[29]:
新用户购买集中在前三个月,三个月后无新用户购买,均为老用户购买
In [30]:
rfm=df.pivot_table(index='ID',values=['NUM','TOTAL','DATE'],aggfunc={'NUM':'sum','TOTAL':'sum','DATE':'max'})
rfm
Out[30]:
In [31]:
rfm['R']=-(rfm['DATE']-rfm['DATE'].max())/np.timedelta64(1,'D')
rfm
Out[31]:
In [32]:
rfm.rename(columns={'NUM':'F','TOTAL':'M'},inplace=True)
In [33]:
rfm.drop(columns=['DATE'],inplace=True)
rfm
Out[33]:
In [34]:
def rfm_fumc(x):
level = x.apply(lambda x:'1' if x>=1 else '0')
label=level.R+level.F+level.M
d={
'111':'重要价值客户',
'011':'重要保持客户',
'101':'重要发展客户',
'001':'重要挽留客户',
'110':'一般价值客户',
'010':'一般保持客户',
'100':'一般发展客户',
'000':'一般挽留客户',
}
result=d[label]
return result
In [35]:
rfm['label']=rfm[['R','F','M']].apply(lambda x: x-x.mean()).apply(rfm_fumc,axis=1)
In [36]:
rfm.loc[rfm.label=='重要价值客户','color']='g'
rfm.loc[~(rfm.label=='重要价值客户'),'color']='r'
rfm.plot.scatter('F','R',c=rfm.color)
Out[36]:
In [37]:
rfm.groupby('label').sum()
Out[37]:
从RFM分层可知,大部分用户为重要保持客户,但是这是由于极值的影响,所有RFM的划分标准应该以业务为准
- 尽量用小部分的用户覆盖大部分的额度
- 不要为了数据好看划分等级
In [38]:
pivoted_counts=df.pivot_table(index='ID',columns='month',values='DATE',aggfunc='count').fillna(0)
pivoted_counts
Out[38]:
In [39]:
df_purchase=pivoted_counts.applymap(lambda x:1 if x>0 else 0)
df_purchase
Out[39]:
In [40]:
def active_status(data):
status=[]
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:
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
In [41]:
puchaser_status=df_purchase.apply(active_status,axis=1)
In [42]:
puchaser_status
Out[42]:
In [43]:
purchase_static_ct=puchaser_status.replace('unreg',np.nan).apply(lambda x:pd.value_counts(x))
purchase_static_ct
Out[43]:
In [44]:
purchase_static_ct.fillna(0).T.apply(lambda x:x/x.sum(),axis=1)
Out[44]:
由上表可知,每月的用户消费状态变化
- 活跃用户,持续消费的用户,对应的是消费运营的质量
- 回流用户,之前不消费本月才消费,对应的是换回运营
- 不活跃用户,对应的是流失
In [45]:
diff=grouped_user.apply(lambda x :x.DATE-x.DATE.shift())
In [46]:
diff.reset_index().DATE.describe()
Out[46]:
In [47]:
(diff/np.timedelta64(1,'D')).hist(bins=20)
Out[47]:
- 订单周期呈指数分布
- 用户的平均购买周期是68天
- 绝大部分用户的购买周期都低于100天
In [48]:
(user_life['max']-user_life['min']).describe()
Out[48]:
In [49]:
((user_life['max']-user_life['min'])/np.timedelta64(1,'D')).hist(bins=40)
Out[49]:
- 用户的生命周期受只购买一次的用户影响比较厉害(可以排除)
- 用户均消费134天, 中位数仅0天
In [50]:
u_1=((user_life['max']-user_life['min'])/np.timedelta64(1,'D')).reset_index()[0]
u_1[u_1>0].hist(bins=40)
Out[50]:
4.复购率与回购率分析¶
- 复购率
- 自然月内,购买多次的用户占总用户比
- 回购率
- 曾经购买过的用户在某一时期内的再次购买的占比
In [51]:
pivoted_counts
Out[51]:
In [52]:
(((pivoted_counts[pivoted_counts>1]).count())/((pivoted_counts[pivoted_counts>0]).count())).plot()
Out[52]: