本次分析数据来源CDNow⽹站的⽤户在1997年1⽉1⽇⾄1998年6⽉30⽇期间内购买CD交易明细。——提取码: va7h
数据集⼀共有⽤户ID,购买⽇期,订单数,订单⾦额四个字段。
import numpy as npimport pandas as pd
from datetime import datetimeimport matplotlib.pyplot as pltimport seaborn as sns%matplotlib inline
#读取数据#4列特征,分别为⽤户id,购买⽇期,购买数量,购买⾦额columns=['user_id','order_dt','order_products','order_amount']data=pd.read_table('./CDNOW_master.txt',names=columns,sep='\\s+')data.head()
user_id
01234
12233
order_dt1997010119970112199701121997010219970330
order_products
11522
order_amount
11.7712.0077.0020.7620.76
data.describe() # 数据的基本信息user_id
countmeanstdmin25%50%75%max
69659.00000011470.85926819.9048481.0000005506.00000011410.00000017273.00000023570.000000
order_dt6.965900e+041.997228e+073.837735e+031.997010e+071.997022e+071.997042e+071.997111e+071.998063e+07
order_products69659.0000002.4100402.3339241.0000001.0000002.0000003.00000099.000000
order_amount69659.00000035.3836.2819420.00000014.49000025.98000043.7000001286.010000
从上可知,看数据6关键指标:样本数:69659,最⼩值:0,最⼤值:1286,平均值:36,⽅差36,中位数:26。平均数⼤于中位数,右偏分布。没有空缺数据,不⽤清理直接分析,注意到⽇期数据是整数型,需要转换成时间格式。
#增加两个新时间序列#将order_dt转化成时间格式data['order_date']=pd.to_datetime(data.order_dt,format='%Y%m%d')#将order_date转化成每⽉起始第⼀天#将order_date转化成每⽉起始第⼀天data['month']=data.order_date.values.astype('datetime[M]')#按⽤户ID进⾏分组user_grouped=data.groupby('user_id').sum()user_grouped
order_dt
user_id
12345671011
199701013994022411983360279882233219686137199701015992143415977205992122219970121790766
order_productsorder_amount
161672911818634
11.77.00156.46100.50385.6120.992.67197.6695.8539.3158.55
12user_id131415161718192021222324252627282930...23123223323423523623723823923550235512355223553235235552355623557235582355923560235612356223563235235652356623567235682356923570
order_dt1997010119970101199701011997010179882450199701011997010439940711399402193994021419970101199701013995022115980481339940227399402195991053623965633539940315
...3994072719970325199703255992091997032519970325399407321997032519970325199703251198243823994072839940653399505269987368513981401719970325791692599114701997032559930982199703253994132959911976199703251997032519970325599111521997032539940651
order_products
4
424851114124126107282...25212112222124831415111816235121625
order_amount
57.06
72.9429.9252.8779.8773.2214.96175.12653.0175.1114.3724.7457.77137.53102.69135.8790.99435.8128.34...57.3477.4350.76134.6324.9913.9723.23.27.1325.282.6349.38.5836.371.18203.0014.37145.60111.6518.3683.4629.3358.7570.0111.7736.0020.97121.7025.7494.08
23570 rows × 3 columns
user_grouped.describe()
order_dt
countmeanstdmin25%50%75%max
2.357000e+045.902627e+079.460684e+071.997010e+071.997021e+071.997032e+075.992125e+074.334408e+09
order_products23570.0000007.12265616.9835311.0000001.0000003.0000007.0000001033.000000
order_amount23570.000000106.080426240.9251950.00000019.97000043.395000106.47500013990.930000
原表只按订单来记录,现按⽤户分组看数据集概述。
从购买数量(单位:PC)⾓度看,⽤户数量:23570,平均值购买7张,最多购买1033张,属于狂热⽤户,中位数3张,平均值⼤于中位数,是右偏分布,存在⼩部分购买多张碟的⽤户。
从消费⾦额(单位:美元)⾓度看,平均数106,最⾼值:13990,属于⼟豪⽤户,中位数43,平均值⼤于中位数,是右偏分布,存在⼩部分⾼消费⽤户。
#设定绘图风格plt.style.use('ggplot')
plt.rcParams['font.sans-serif']=['SimHei']
ax=data.groupby('month').order_products.sum().plot()ax.set_xlabel('⽉份')ax.set_ylabel('数量(张)')
ax.set_title('不同⽉份的⽤户购买数量')plt.show()
ax=data.groupby('month').order_amount.sum().plot()ax.set_xlabel('⽉份')ax.set_ylabel('消费⾦额')
ax.set_title('不同⽉份的⽤户消费⾦额')plt.show()
由图⽚可知,⽆论是消费⾦额还是CD碟数都呈现相同的趋势,⽽且前三⽉数据都呈现出异常状态,由于我们不知道原数据到底从何获得,只能做出这三个⽉有促销活动,抑或是这是新开的店之类的,前三个⽉⼤多都是新⼈之类的假设,我们不得⽽知,继续往下看。
ax=data.groupby('user_id').sum().plot.scatter('order_amount','order_products')ax.set_xlabel('消费⾦额')ax.set_ylabel('数量')
ax.set_title('每个⽤户消费⾦额与购买个数的关系')plt.show()
每个⽤户的消费⾦额跟购买数量呈现⼀定的线性关系。
plt.figure(figsize=(12,4))ax=plt.subplot(121)
ax=data.groupby('user_id').order_products.sum().plot.hist(bins=50)ax.set_xlabel('数量')ax.set_ylabel('⽤户数')ax.set_xlim(0,150)
ax.set_title('⽤户购买数量分布直⽅图')ax1=plt.subplot(122)
ax1=data.groupby('user_id').order_amount.sum().plot.hist(bins=50)ax1.set_xlabel('消费⾦额')ax1.set_ylabel('⽤户⼈数')ax1.set_xlim(0,2000)
ax1.set_title('⽤户消费⾦额分布直⽅图')plt.show(ax,ax1)
我们可以从直⽅图看到,⼤部分⽤户的消费能⼒确实不⾼,整个计算周期⾥的购买碟数在20张以内,消费⾦额在250美⾦以内,再图上⼏乎看不到⾼消费⽤户。
data.groupby('user_id').month.min().value_counts()1997-02-01 84761997-01-01 78461997-03-01 7248Name: month, dtype: int
data.groupby('user_id').month.max().value_counts()1997-02-01 49121997-03-01 44781997-01-01 41921998-06-01 15061998-05-01 10421998-03-01 9931998-04-01 7691997-04-01 6771997-12-01 6201997-11-01 6091998-02-01 5501998-01-01 5141997-06-01 4991997-07-01 4931997-05-01 4801997-10-01 4551997-09-01 3971997-08-01 384Name: month, dtype: int
我们可以看到,貌似每个⽤户的第⼀次购买记录都是前三个⽉,最后次购买记录也是前三个⽉居前三。由此我们可以推测,这份数据集⼤概是选择了这三个⽉时间段消费的⽤户在后⾯的18个⽉的追踪记录数据。也能很好的解释我们之前看到的前三个⽉⽆论是消费⾦额还是购买数量的异常。
#创建数据透视表,对每个⽤户的每⽉订单数计数pivoted_count=data.pivot_table(index='user_id',columns='month',values='order_dt',aggfunc='count').fillna(0)pivoted_count.head()
month
1997-01-01
1997-02-01
1997-03-01
1997-04-01
1997-05-01
1997-06-01
1997-07-01
1997-08-01
1997-09-01
1997-10-01
1997-11-01
1997-12-01
1998-01-01
1998-02-01
1998-03-01
1998-04-01
1998-05-01
1998-06-01
user_id
12345
1.02.01.02.02.0
0.00.00.00.01.0
0.00.01.00.00.0
0.00.01.00.01.0
0.00.00.00.01.0
0.00.00.00.01.0
0.00.00.00.01.0
0.00.00.01.00.0
0.00.00.00.01.0
0.00.00.00.00.0
0.00.02.00.00.0
0.00.00.01.02.0
0.00.00.00.01.0
0.00.00.00.00.0
0.00.00.00.00.0
0.00.00.00.00.0
0.00.01.00.00.0
0.00.00.00.00.0
pivoted_count_transf =pivoted_count.applymap(lambda x:1 if x>1 else np.NAN if x ==0 else 0)pivoted_count_transf.head()
month
1997-01-01
1997-02-01
1997-03-01
1997-04-01
1997-05-01
1997-06-01
1997-07-01
1997-08-01
1997-09-01
1997-10-01
1997-11-01
1997-12-01
1998-01-01
1998-02-01
1998-03-01
1998-04-01
1998-05-01
1998-06-01
user_id
12345
0.01.00.01.01.0
NaNNaNNaNNaN0.0
NaNNaN0.0NaNNaN
NaNNaN0.0NaN0.0
NaNNaNNaNNaN0.0
NaNNaNNaNNaN0.0
NaNNaNNaNNaN0.0
NaNNaNNaN0.0NaN
NaNNaNNaNNaN0.0
NaNNaNNaNNaNNaN
NaNNaN1.0NaNNaN
NaNNaNNaN0.01.0
NaNNaNNaNNaN0.0
NaNNaNNaNNaNNaN
NaNNaNNaNNaNNaN
NaNNaNNaNNaNNaN
NaNNaN0.0NaNNaN
NaNNaNNaNNaNNaN
消费⾏为中的复购率和回购率
复购率:复购率的定义是在某时间窗⼝内消费两次及以上的⽤户在总消费⽤户中占⽐。这⾥的时间窗⼝是⽉,如果⼀个⽤户在同⼀天下了两笔订单,这⾥也将他算作复购⽤户。
# 复购率db=pivoted_count_transf.sum()/pivoted_count_transf.count()ax=db.plot(figsize=(10,4))ax.set_xlabel('时间(⽉)')ax.set_ylabel('百分⽐(%)')ax.set_title('每⽉⽤户复购率图')plt.show()
从图中我们可以看出复购率因为⼤量新⽤户加⼊的关系,不断扩⼤分母,导致初期的复购率不怎么⾼,譬如刚开始的97年⼀⽉份复购率只有6%左右,⽽后直线上升,到第四个⽉后到达最⾼点,因为这次数据集是前三个⽉新客跟踪数据,三个⽉后,没有新客的加⼊,可以认定是前三个⽉的客户⼤浪淘沙剩下的还有购买欲望的⽼客,这时候的复购率⽐较稳定,在20%左右徘徊。
fig,ax=plt.subplots(figsize=(10,4))ax.plot(pivoted_count_transf.sum())ax.plot(pivoted_count_transf.count())ax.set_xlabel('时间(⽉)')ax.set_ylabel('⽤户数(⼈)')
ax.set_title('每⽉消费和⼆次消费以上⽤户数')legends=['⼆次消费以上⼈数','消费⼈数']ax.legend(legends,loc='upper right')plt.show()
如图所⽰,三个⽉后,⽤户迅速沉淀,前三个⽉的新客⼤概在11正负387左右⼈数继续消费波动,⽽⼆次消费的客户则很稳定,曲线也趋近直线,⼤概在400⼈左右波动。这部分的客户放到现实中应该是重点维护的优质客户。
回购率:回购率是某⼀个时间窗⼝内消费的⽤户,在下⼀个时间窗⼝仍旧消费的占⽐。我前⼀⽉消费⽤户1000,后⼀个⽉他们中仍有200个消费,则回购率是20%。由于牵扯两个时间窗⼝的计算,所以较之复购率稍稍复杂点。
pivoted_amount=data.pivot_table(index='user_id',columns='month',values='order_dt',aggfunc='count').fillna(0)#转化数据,有过购买⾏为的为1,没有购买⾏为的为0
pivoted_purchase=pivoted_amount.applymap(lambda x:1 if x>0 else 0)pivoted_purchase.head()
month
1997-01-01
1997-02-01
1997-03-01
1997-04-01
1997-05-01
1997-06-01
1997-07-01
1997-08-01
1997-09-01
1997-10-01
1997-11-01
1997-12-01
1998-01-01
1998-02-01
1998-03-01
1998-04-01
1998-05-01
1998-06-01
user_id
1234
1111
0000
0010
0010
0000
0000
0000
0001
0000
0000
0010
0001
0000
0000
0000
0000
0010
0000
5month
1997-101-011997-102-011997-003-011997-104-011997-105-011997-106-011997-107-011997-008-011997-109-011997-010-011997-011-011997-112-011998-101-011998-002-011998-003-011998-004-011998-005-011998-006-01
#定义函数,每个⽉都要跟后⾯⼀个⽉对⽐下,本⽉有消费且下⽉也有消费,则本⽉记为1,user_id
#下⽉没有消费则为0,本⽉没有消费则为NaN,由于最后个⽉没有下⽉数据,规定全为NaNdef purchase_return(data): 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) status.append(np.NaN) return pd.Series(status)#应⽤并且绘图
pivoted_purchase_return=pivoted_purchase.apply(purchase_return,axis=1)pivoted_purchase_return.head()
0
user_id
12345
0.00.00.00.01.0
12345671011121314151617
NaNNaNNaNNaN0.0
NaNNaN1.0NaNNaN
NaNNaN0.0NaN1.0
NaNNaNNaNNaN1.0
NaNNaNNaNNaN1.0
NaNNaNNaNNaN0.0
NaNNaNNaN0.0NaN
NaNNaNNaNNaN0.0
NaNNaNNaNNaNNaN
NaNNaN0.0NaNNaN
NaNNaNNaN0.01.0
NaNNaNNaNNaN0.0
NaNNaNNaNNaNNaN
NaNNaNNaNNaNNaN
NaNNaNNaNNaNNaN
NaNNaN0.0NaNNaN
NaNNaNNaNNaNNaN
columns=data.month.sort_values().unique()pivoted_purchase_return.columns = columns
ax=(pivoted_purchase_return.sum()/pivoted_purchase_return.count()).plot(figsize=(10,4))ax.set_xlabel('时间(⽉)')ax.set_ylabel('百分⽐(%)')
ax.set_title('⼗⼋个⽉内⽤户回购率图')plt.show()
fig,ax=plt.subplots(figsize=(10,4))ax.plot(pivoted_purchase_return.sum())ax.plot(pivoted_purchase_return.count())ax.set_xlabel('时间(⽉)')ax.set_ylabel('⽤户数(⼈)')
legends = ['每⽉回购⼈数','每⽉消费⼈数']ax.legend(legends,loc = 'upper right')plt.show()
由图可知,⽤户的回购率⼤于复购率,约在30%左右正负五个点波动,看⼈数分布表则发现回购⼈数趋近稳定,那么波动则是偶尔⽉份间的消费⼈数基数的变动,可能有营销者淡旺季,但是这部分回购⽤户的消费⾏为⼤抵稳定,应该跟之前每⽉复购的⽤户有⼀定重合,是属于优质⽤户。对回购率和复购率进⾏综合分析,可以得出,新客的整体质量低于⽼客,⽼客的忠诚度(回购率)表现较好,消费频次稍次,这是这个⽹站的⽤户消费特征
(3)消费⾏为中的⽤户分层
我们按照⽤户的消费⾏为,简单划分成⼏个维度:新⽤户、活跃⽤户、不活跃⽤户、回流⽤户。新⽤户(new):新⽤户的定义是第⼀次消费的⽤户。活跃⽤户(active):即连续两个时间窗⼝都消费过的⽤户。
不活跃⽤户(unactive):不活跃⽤户则是时间窗⼝内没有消费过的活跃⽤户,即⼀⼆⽉份都消费过,三⽉份没消费过。回流⽤户(return):回流⽤户是在上⼀个窗⼝中没有消费,⽽在当前时间窗⼝内有过消费。
def active_status(date): status=[]
for i in range(18): #若本⽉没有消费 if date[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 pd.Series(status)
pivoted_purchase_status=pivoted_purchase.apply(active_status,axis=1)pivoted_purchase_status.columns=columnspivoted_purchase_status.head()
1997-01-01
user_id
12345
newnewnewnewnew
1997-02-01
1997-03-01
1997-04-01
1997-05-01
1997-06-01
1997-07-01
1997-08-01
1997-09-01
1997-10-01
1997-11-01
1997-12-01
1998-01-01
1998-02-01
1998-03-01
1998-04-01
1998-05-01
unactiveunactiveunactiveunactiveactive
unactiveunactivereturnunactiveunactive
unactiveunactiveactiveunactivereturn
unactiveunactiveunactiveunactiveactive
unactiveunactiveunactiveunactiveactive
unactiveunactiveunactiveunactiveactive
unactiveunactiveunactivereturnunactive
unactiveunactiveunactiveunactivereturn
unactiveunactiveunactiveunactiveunactive
unactiveunactivereturnunactiveunactive
unactiveunactiveunactivereturnreturn
unactiveunactiveunactiveunactiveactive
unactiveunactiveunactiveunactiveunactive
unactiveunactiveunactiveunactiveunactive
unactiveunactiveunactiveunactiveunactive
unactiveunactivereturnunactiveunactive
这个函数主要分为两部分的判断,以本⽉是否消费为界。本⽉若没有消费,则判断是不是第⼀个⽉,是的话直接返回unreg(不辨别),不是第⼀个⽉的话,我们就可以找出前⼀⽉标签,前⼀个⽉还是不辨别的话,就返回unreg(不辨别),因为这个⽉还是没消费,如果前⼀个⽉是新课还是活跃⽤户,还是回流⽤户,因为这个⽉都没消费,重新定义为unactive(不活跃⽤户)。
本⽉若有消费,则需要判断是不是第⼀次消费,若是第⼀⽉的消费,因为没有前⼀个⽉数据,所以直接是new(新客)。接下来就是不是第⼀个⽉⼜有消费的情况了,此时可以找出前⼀个⽉的标签,如果前⼀个⽉是不活跃,则返回return(回流⽤户),如果是unreg,则是第⼀次消费,返回new(新客),剩下的就是前⼀个⽉是新客或者是活跃⽤户了,此时都返回active(活跃⽤户)。
pivoted_status_counts=pivoted_purchase_status.replace('unreg',np.NaN).apply(pd.value_counts)pivoted_status_counts.head()
1997-01-01
activenewreturnunactive
NaN7846.0NaNNaN
1997-02-011157.08476.0NaN66.0
1997-03-011681724859514046
1997-04-011773.0NaN1049.020748.0
1997-05-01852.0NaN1362.021356.0
1997-06-01747.0NaN1592.021231.0
1997-07-01746.0NaN1434.021390.0
1997-08-01604.0NaN1168.021798.0
1997-09-01528.0NaN1211.021831.0
1997-10-01532.0NaN1307.021731.0
1997-11-01624.0NaN1404.0212.0
1997-12-01632.0NaN1232.021706.0
1998-01-01512.0NaN1025.022033.0
1998-02-01472.0NaN1079.022019.0
1998-03-01571.0NaN14.021510.0
1998-04-01518.0NaN919.022133.0
1998-05-01459.0NaN1029.022082.0
1998-06-01446.0
1060.0220.0ax=pivoted_status_counts.fillna(0).T.plot.area(figsize=(12,6))ax.set_xlabel('时间(⽉)')ax.set_ylabel('⽤户数(⼈)')
ax.set_title('每⽉各类⽤户类型占⽐⾯积图')ax.legend(loc='upper left')plt.show()
由图可知,⿊⾊的不活跃⽤户始终是占据⼤头的,这也跟我们之前的图表结果相符,其次红⾊代表的活跃⽤户⾮常稳定,是属于核⼼⽤户,以及紫⾊的回流⽤户,这两个分层相加,⼤抵是当⽉的消费⽤户⼈数的占⽐,与我们之前的复购率和回购率的表结果⼀致,这两层的⽤户⼤抵接近两千⼈左右。
回流占⽐:某个时间窗⼝内回流⽤户在总⽤户中的占⽐。活跃占⽐:某个时间窗⼝内活跃⽤户在总⽤户中的占⽐。
return_rate=pivoted_status_counts.apply(lambda x:x/x.sum())ax=return_rate.loc['return'].plot(figsize=(12,6))ax.set_xlabel('时间(⽉)')ax.set_ylabel('百分数(%)')ax.set_title('每⽉回流⽤户占⽐')plt.show()
ax = return_rate.loc['active'].plot(figsize = (12,6))ax.set_xlabel('时间(⽉)')ax.set_ylabel('百分数(%)') ax.set_title('每⽉活跃⽤户占⽐')plt.show()
由图可知,⽤户回流占⽐在5%~8%之间波动,趋势向下,有客户流失的预警。⽤户活跃占⽐在3%~5%间,作为连续消费⽤户,质量在⼀定程度上⾼于回流⽤户。结合回流⽤户和活跃⽤户看,在后期的消费⽤户中,60%是回流⽤户,40%是活跃⽤户,整体质量还好,但是针对这两个分层依旧有改进的空间,可以继续细化数据。
(4)⽤户质量
因为消费⾏为有明显的⼆⼋倾向,我们需要知道⾼质量⽤户为消费贡献了多少份额。
user_amount=data.groupby('user_id').order_amount.sum().sort_values().reset_index()user_amount['amount_cumsum']=user_amount.order_amount.cumsum()user_amount.tail()
user_id
2356523566235672356823569
7931193397983140487592
order_amount
97.186552.706973.0776.3313990.93
amount_cumsum
2463822.602470375.302477348.372486324.702500315.63
#计算出各阶段⾦额占总⾦额的百分⽐amount_total = user_amount.amount_cumsum.max()
user_amount['prop'] = user_amount.amount_cumsum.apply(lambda x: x / amount_total)ax = user_amount.prop.plot()ax.set_xlabel('⼈数(⼈)') ax.set_ylabel('百分数(%)') ax.set_title('⽤户累计贡献⾦额百分⽐')plt.show()
由图我们可以清晰的看到,⾦额排名靠后的15000名⽤户才贡献不到20%的销售量,⽽此次数据集的总⽤户⼈数为23569⼈,我们可以进⼀步再看,排名靠后的20000名⽤户,贡献了接近40%的消费⾦额,也就是说后⾯的3569⼈接近贡献了60%的消费⾦额,如果我们换算成⾦额/⼈单位,这后⾯的3569名客户相当于签名20000名客户的8.4倍!这也反应了在消费领域中,狠抓⾼质量⽤户是万古不变的道理。
(5)⽤户⽣命周期
这⾥我们定义第⼀次消费⾄最后⼀次消费为整个⽤户⽣命。我们需要找出每个⽤户的第⼀次消费和最后次消费
#⽤户⽣命周期user_purchase = data[['user_id','order_products','order_amount','order_date']]order_date_min=user_purchase.groupby('user_id').order_date.min()order_date_max=user_purchase.groupby('user_id').order_date.max()life_time = (order_date_max-order_date_min).reset_index()display(life_time.head(),life_time.describe())
user_id
01234
12345
order_date0 days0 days511 days345 days367 days
user_id
countmeanstdmin25%50%75%max
23570.00000011785.5000006804.2172581.00000053.25000011785.50000017677.75000023570.000000
order_date
23570
134 days 20:55:36.987696180 days 13:46:43.039788
0 days 00:00:000 days 00:00:000 days 00:00:00294 days 00:00:004 days 00:00:00
由描述可知,所有⽤户的平均⽣命周期是134天,中位数是0天,也就是存在⼀半的⽤户是第⼀次消费就是最后次消费,也就是我们前⾯所说的低质量客户。⽽最⼤是4天,相当于我们这个数据集的总天数,说明这⽤户是从开始到最后都有消费意愿的⾼质量⽤户。
因为数据中的⽤户都是前三个⽉第⼀次消费,所以这⾥的⽣命周期代表的是1⽉~3⽉⽤户的⽣命周期。因为这⾥数据只截取到了18个⽉为⽌,这时间过后,⽤户仍然会持续消费,所以理论上,⽤户的平均⽣命周期还会增长。接下来我们看下直⽅图的分布,更加直观。
life_time['life_time'] = life_time.order_date/np.timedelta(1,'D')ax=life_time.life_time.plot.hist(bins =100,figsize = (12,6))ax.set_xlabel('天数(天)')ax.set_ylabel('⼈数(⼈)')
ax.set_title('⼆次消费以上⽤户的⽣命周期直⽅图')plt.show()
life_time['life_time'] = life_time.order_date/np.timedelta(1,'D')
ax=life_time[life_time.life_time>0].life_time.plot.hist(bins =100,figsize = (12,6))ax.set_xlabel('天数(天)')ax.set_ylabel('⼈数(⼈)')
ax.set_title('⼆次消费以上⽤户的⽣命周期直⽅图')plt.show()
看图我们可以出图像呈双峰结构,部分质量差的⽤户,虽然消费了两次,但是仍旧⽆法持续,此时若想提⾼点⽤户转化率,应在⽤户⾸次消费30天内应该尽量引导,不然就会流失。少部分⽤户集中在50天~300天,属于普通型的⽣命周期,有⼀定忠诚度。⾼质量⽤户的⽣命周期,集中在400天以后,这时候途中⼈数⼜逐渐上升,这已经属于⾼忠诚⽤户了,尽量维护好这批⾼质量⽤户。
消费两次以上⽤户的⽣命周期接近消费只有⼀次⽤户的两倍,所以如何在⽤户⾸次消费后进⾏有效的引导促使其多次消费,可以有效的提⾼⽤户的⽣命周期和⽤户质量
len(life_time[life_time.life_time > 400]) #结果:36513651
我们同时计算了⽤户⽣命周期⼤于400天的⼈数,为3651⼈,跟我们之前的⾼贡献率⼈数⾮常接近,暗⽰我们这批⼈应该接近同⼀批⼈,也就是说消费⾦额⾼的⽤户往往他们的⽣命周期也越长,这也符合我们的常规认识。
#链接两表user_purchase_retention = pd.merge(left = user_purchase, right = order_date_min.reset_index(), how = 'inner', on = 'user_id', suffixes=('', '_min'))user_purchase_retention['order_date_diff'] = user_purchase_retention.order_date-user_purchase_retention.order_date_minuser_purchase_retention['date_diff'] = user_purchase_retention.order_date_diff.apply(lambda x: x/np.timedelta(1,'D'))
这⾥⽤到merge函数,它和SQL中的join差不多,⽤来将两个DataFrame进⾏合并。我们选择了inner 的⽅式,对标inner join。即只合并能对应得上的数据。这⾥以on=user_id为对应标准。这⾥merge的⽬的是将⽤户消费⾏为和第⼀次消费时间对应上,形成⼀个新的DataFrame。suffxes参数是如果合并的内容中有重名column,加上后缀。
然后将order_date和order_date_min相减。获得⼀个新的列,为⽤户每⼀次消费距第⼀次消费的时间差值,然后在整除np.timedelta(1,‘D’)来获得⽇期差数值。
user_purchase_retention.head()
user_id
01234
12233
order_products
11522
order_amount
11.7712.0077.0020.7620.76
order_date1997-01-011997-01-121997-01-121997-01-021997-03-30
order_date_min1997-01-011997-01-121997-01-121997-01-021997-01-02
order_date_diff
0 days0 days0 days0 days87 days
date_diff
0.00.00.00.087.0
def convert(date): if date==0.0: return np.NaN elif 0 然后将时间差值分桶。我这⾥分成0~30天内,30~60天内,60~90天等,代表⽤户当前消费时间距第⼀次消费属于哪个时间段呢。这⾥date_diff=0并没有被划分⼊0~30天,因为计算的是留存率,如果⽤户仅消费了⼀次,留存率应该是0。另外⼀⽅⾯,如果⽤户第⼀天内消费了多次,但是往后没有消费,也算作留存率0。 bin = [0,30,60,90,120,150,180,365] user_purchase_retention['date_diff_bin'] = pd.cut(user_purchase_retention.date_diff, bins = bin) pivoted_retention= user_purchase_retention.groupby(['user_id','date_diff_bin']).order_amount.sum().unstack()pivoted_retention_trans = pivoted_retention.fillna(0).applymap(lambda x: 1 if x >0 else 0)pivoted_retention_trans.head() date_diff_bin user_id 34578 (0, 30](30, 60](60, 90](90, 120](120, 150](150, 180](180, 365] 01100 00101 10000 00100 00100 00101 11111 直接⽤⾦额表达不出留存率,我们还是按照之前的算法,把消费过的转换成1,未消费过的转换成0,毕竟留存率看的是是否有消费。 ax = (pivoted_retention_trans.sum()/pivoted_retention_trans.count()).plot.bar()ax.set_xlabel('时间跨度(天)') ax.set_ylabel('百分数(%)') ax.set_title('各时间段的⽤户留存率')plt.show() 如图,第⼀个⽉的留存率⾼达46%,第⼆个⽉就下降到35%左右,之后⼏个⽉逐渐趋近稳定在25%左右,说明后⾯的⽤户逐渐开始稳定下来,说明通过⽤户在前三个⽉的使⽤中,逐渐开始喜爱本店铺的业务或者转换别家的店铺,所以这时候流失率会增⼤。从运营的⾓度来看,留存的玩家都是⾄少消费两次以上的玩家,⽐起拉新⽤户来讲,如何提⾼这些已消费玩家的持续消费是运营的重点,有些活动还是营销,最好放在前三个⽉,特别是第⼀个⽉来进⾏⽐较好。为了更好的确定营销的最好时机,我们来看看⽤户的平均购买周期。 (6)平均购买周期 平均购买周期:⽤户的两次消费⾏为的时间间隔。 #创建函数,返回时间差def diff(group): d= abs(group.date_diff - group.date_diff.shift(-1)) return d last_diff = user_purchase_retention.groupby('user_id').apply(diff)ax = last_diff.hist(bins = 20)ax.set_xlabel('时间跨度(天)') ax.set_ylabel('⼈数(⼈)') ax.set_title('⽤户平均购买周期直⽅图')plt.show() 如图,典型的长尾分布,⼤部分⽤户的消费间隔确实⽐较短。不妨将时间召回点设为消费后⽴即赠送优惠券,消费后10天询问⽤户CD怎么样,消费后30天提醒优惠券到期,消费后60天短信推送。 因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- hids.cn 版权所有 赣ICP备2024042780号-1
违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务