數(shù)據(jù)集簡(jiǎn)介
數(shù)據(jù)集來(lái)源于某健身房2019年3月至2020年2月會(huì)員消費(fèi)購(gòu)買(mǎi)行為瘟滨,數(shù)據(jù)集一共包含四個(gè)字段:用戶ID,購(gòu)買(mǎi)日期灭衷,購(gòu)買(mǎi)數(shù)量和購(gòu)買(mǎi)金額。屬于非常典型的消費(fèi)行為數(shù)據(jù)集旁涤。
數(shù)據(jù)導(dǎo)入
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt#導(dǎo)入庫(kù)及所需的包
from datetime import datetime
plt.rc('font', family='SimHei', size=18)# 顯示中文標(biāo)簽
plt.style.use ('ggplot')#設(shè)定繪圖風(fēng)格
df=pd.read_excel(r"D:\PycharmProjects\data\cuscapi.xls", order_dt=['date'])# 數(shù)據(jù)加載
df.head(10)
user_id | order_dt | order_products | order_amount | |
---|---|---|---|---|
0 | vs30033073 | 2020-01-17 | 1 | 20 |
1 | vs30026748 | 2019-12-04 | 1 | 20 |
2 | vs10000716 | 2019-07-05 | 1 | 20 |
3 | vs30032785 | 2019-08-21 | 2 | 0 |
4 | vs10000716 | 2019-10-24 | 1 | 20 |
5 | vs30033073 | 2019-11-29 | 2 | 20 |
6 | vs10000621 | 2019-07-19 | 2 | 20 |
7 | vs30029475 | 2019-05-17 | 1 | 20 |
8 | vs30030664 | 2019-11-11 | 1 | 20 |
9 | vs10000773 | 2019-11-25 | 1 | 20 |
pd.set_option('display.float_format', lambda x: '%.2f' % x)
df.describe()
order_products | order_amount | |
---|---|---|
count | 2013.00 | 2013.00 |
mean | 1.47 | 22.90 |
std | 0.91 | 94.94 |
min | 1.00 | 0.00 |
25% | 1.00 | 20.00 |
50% | 1.00 | 20.00 |
75% | 2.00 | 20.00 |
max | 12.00 | 2650.00 |
分析:
1.會(huì)員用戶平均每筆訂單購(gòu)買(mǎi)1.5個(gè)商品翔曲,標(biāo)準(zhǔn)差為在0.9,波性較小 劈愚。中位數(shù)在1個(gè)商品瞳遍,75分位數(shù)在2個(gè)產(chǎn)品,說(shuō)明絕大訂單的購(gòu)買(mǎi)量都不多菌羽。
2.平均每筆訂單消費(fèi)金額為22.9元掠械,標(biāo)準(zhǔn)差約為95,中位數(shù)在20,平均數(shù)大于中位數(shù)份蝴。大多數(shù)會(huì)員消費(fèi)金額集中在小額犁功,小部分用戶貢獻(xiàn)大額消費(fèi),符合消費(fèi)類(lèi)數(shù)據(jù)的二八分布婚夫。
3.一般而言浸卦,消費(fèi)類(lèi)數(shù)據(jù)的分布都是長(zhǎng)尾分布。
user_group=df.groupby('user_id').sum()
user_group.head(10)
user_id | order_products | order_amount |
---|---|---|
vs10000005 | 9 | 189 |
vs10000621 | 214 | 5704 |
vs10000627 | 2 | 0 |
vs10000716 | 250 | 2616 |
vs10000743 | 1 | 20 |
vs10000757 | 75 | 1104 |
vs10000773 | 23 | 460 |
vs10000775 | 8 | 2730 |
vs10000788 | 7 | 144 |
vs10000794 | 1 | 0 |
user_group.describe()
order_products | order_amount | |
---|---|---|
count | 247.00 | 247.00 |
mean | 11.97 | 186.59 |
std | 36.70 | 641.12 |
min | 1.00 | 0.00 |
25% | 2.00 | 0.00 |
50% | 2.00 | 0.00 |
75% | 3.00 | 66.00 |
max | 277.00 | 5704.00 |
分析:會(huì)員用戶平均購(gòu)買(mǎi)約12個(gè)商品案糙,最多的購(gòu)買(mǎi)了277個(gè)商品限嫌。會(huì)員用戶平均消費(fèi)金額約為187元,標(biāo)準(zhǔn)差為641时捌,中位數(shù)在0怒医,結(jié)合分位數(shù)和最大值看,屬于正偏分布奢讨,存在小部分會(huì)員購(gòu)買(mǎi)大量商品的高消費(fèi)情況稚叹。
df.info()#查看數(shù)據(jù)類(lèi)型
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 2013 entries, 0 to 2012
Data columns (total 4 columns):
user_id 2013 non-null object
order_dt 2013 non-null datetime64[ns]
order_products 2013 non-null int64
order_amount 2013 non-null int64
dtypes: datetime64[ns](1), int64(2), object(1)
memory usage: 63.0+ KB
分析:經(jīng)查,本數(shù)據(jù)集不存在空值拿诸。
數(shù)據(jù)處理
數(shù)據(jù)類(lèi)型轉(zhuǎn)換
#提取月份
df['order_dt']=df['order_dt'].dt.date
df['month']=df['order_dt'].astype('datetime64[M]')
df.head(10)
user_id | order_dt | order_products | order_amount | month | |
---|---|---|---|---|---|
0 | vs30033073 | 2020-01-17 | 1 | 20 | 2020-01-01 |
1 | vs30026748 | 2019-12-04 | 1 | 20 | 2019-12-01 |
2 | vs10000716 | 2019-07-05 | 1 | 20 | 2019-07-01 |
3 | vs30032785 | 2019-08-21 | 2 | 0 | 2019-08-01 |
4 | vs10000716 | 2019-10-24 | 1 | 20 | 2019-10-01 |
5 | vs30033073 | 2019-11-29 | 2 | 20 | 2019-11-01 |
6 | vs10000621 | 2019-07-19 | 2 | 20 | 2019-07-01 |
7 | vs30029475 | 2019-05-17 | 1 | 20 | 2019-05-01 |
8 | vs30030664 | 2019-11-11 | 1 | 20 | 2019-11-01 |
9 | vs10000773 | 2019-11-25 | 1 | 20 | 2019-11-01 |
數(shù)據(jù)分析-月度總趨勢(shì)分析
df.groupby('month').order_amount.sum().plot()
plt.xlabel('月份')
plt.ylabel('消費(fèi)金額(元)')
plt.title('不同月份的用戶消費(fèi)金額',fontsize=20)
分析:按月統(tǒng)計(jì)每個(gè)月的商品消費(fèi)金額扒袖,可以看到,各月份銷(xiāo)量波動(dòng)起伏較大亩码。
df.groupby('month').order_products.sum().plot()
plt.xlabel('月份')
plt.ylabel('商品個(gè)數(shù)')
plt.title('不同月份的產(chǎn)品購(gòu)買(mǎi)量',fontsize=20)
說(shuō)明:每月的產(chǎn)品購(gòu)買(mǎi)量呈現(xiàn)前7個(gè)月快速上升季率,后5個(gè)月整體下降的趨勢(shì)。
df.groupby('month').user_id.count().plot()
plt.xlabel('月份')
plt.ylabel('消費(fèi)次數(shù)')
plt.title('不同月份的消費(fèi)次數(shù)',fontsize=20)
說(shuō)明:至7月份消費(fèi)次數(shù)超過(guò)250次描沟,后續(xù)月份的消費(fèi)次數(shù)開(kāi)始呈現(xiàn)下降趨勢(shì)飒泻。
df.groupby('month').user_id.nunique().plot()
plt.xlabel('月份')
plt.ylabel('消費(fèi)人數(shù)')
plt.title('不同月份的消費(fèi)人數(shù)',fontsize=20)
說(shuō)明:每月的消費(fèi)人數(shù)小于每月的消費(fèi)次數(shù)。至7月份消費(fèi)人數(shù)達(dá)90人吏廉,后續(xù)月份的消費(fèi)人數(shù)開(kāi)始呈現(xiàn)下降趨勢(shì)泞遗。
數(shù)據(jù)分析-用戶個(gè)體行為分析
df.groupby('user_id').sum().head()
user_id | order_products | order_amount |
---|---|---|
vs10000005 | 9 | 189 |
vs10000621 | 214 | 5704 |
vs10000627 | 2 | 0 |
vs10000716 | 250 | 2616 |
vs10000743 | 1 | 20 |
user_consume=df.groupby('user_id').sum()
plt.scatter(user_consume['order_products'], user_consume['order_amount'] )
plt.xlabel('消費(fèi)產(chǎn)品個(gè)數(shù)')
plt.ylabel('消費(fèi)金額')
plt.title('用戶消費(fèi)金額與產(chǎn)品個(gè)數(shù)的關(guān)系散點(diǎn)圖',fontsize=20)
說(shuō)明:訂單消費(fèi)金額和訂單商品量的關(guān)系不呈線性,用戶消費(fèi)規(guī)律性不強(qiáng)席覆,訂單的極值較多刹孔。
consume_products = user_consume['order_products']
consume_amount= user_consume['order_amount']
fig= plt.figure(figsize=(10.,6))
fig.add_subplot(1,2,1)
consume_products.hist(bins=10 )
plt.title('用戶購(gòu)買(mǎi)數(shù)量分布直方圖')
plt.xlabel('購(gòu)買(mǎi)數(shù)量')
plt.ylabel('人數(shù)')
fig.add_subplot(1,2,2)
consume_amount.hist(bins=10)
plt.title('用戶購(gòu)買(mǎi)金額分布直方圖')
plt.xlabel('購(gòu)買(mǎi)金額')
plt.ylabel('人數(shù)')
說(shuō)明:大部分用戶消費(fèi)能力不高,整個(gè)計(jì)算周期內(nèi)購(gòu)買(mǎi)數(shù)量在50以內(nèi)娜睛,消費(fèi)金額在1000以內(nèi)。
df.groupby('user_id').month.min().value_counts()
2019-08-01 62
2019-07-01 53
2019-09-01 43
2019-10-01 22
2019-11-01 16
2019-03-01 13
2020-01-01 11
2019-06-01 9
2019-05-01 8
2019-12-01 5
2020-02-01 3
2019-04-01 2
Name: month, dtype: int64
df.groupby('user_id').month.min().value_counts().plot()
plt.title('第一次消費(fèi)會(huì)員數(shù)和時(shí)間折線圖')
plt.xlabel('首購(gòu)時(shí)間')
plt.ylabel('會(huì)員數(shù)')
df.groupby('user_id').month.max().value_counts()
2019-08-01 65
2019-09-01 52
2019-07-01 39
2019-10-01 22
2020-01-01 21
2020-02-01 17
2019-11-01 16
2019-12-01 8
2019-03-01 3
2019-06-01 3
2019-05-01 1
Name: month, dtype: int64
df.groupby('user_id').month.max().value_counts().plot()
plt.title('最后一次消費(fèi)會(huì)員數(shù)和時(shí)間折線圖')
plt.xlabel('最后購(gòu)買(mǎi)時(shí)間')
plt.ylabel('會(huì)員數(shù)')
#各會(huì)員首次卦睹、最后一次消費(fèi)時(shí)間間隔
(df.groupby('user_id')['month'].agg({'num1':'min', 'num2':'max'}).num2-df.groupby('user_id')['month'].agg({'num1':'min', 'num2':'max'}).num1).value_counts()
0 days 177
31 days 24
61 days 6
92 days 6
122 days 6
337 days 5
30 days 4
306 days 3
153 days 3
184 days 3
62 days 2
123 days 2
215 days 2
245 days 2
275 days 1
276 days 1
dtype: int64
說(shuō)明:
1.用groupby函數(shù)將用戶分組畦戒,并且求月份的最小值、最小值即用戶消費(fèi)行為的第一次消費(fèi)時(shí)間结序。
2.大部分用戶的第一次消費(fèi)集中在7障斋、8月份,觀察用戶的最后一次消費(fèi)時(shí)間,將近80%的客戶都在首次消費(fèi)1個(gè)月內(nèi)流失垃环。
數(shù)據(jù)分析-用戶行為中的復(fù)購(gòu)率和回購(gòu)率分析
數(shù)據(jù)透視-每位會(huì)員各月消費(fèi)次數(shù)
#統(tǒng)計(jì)用戶消費(fèi)次數(shù)
pivoted_counts=df.pivot_table(index='user_id',columns='month',values='order_dt',aggfunc='count').fillna(0)
columns_month=df.month.dt.date.sort_values().unique()
pivoted_counts.columns=columns_month
pivoted_counts.head()
user_id | 2019-03-01 | 2019-04-01 | 2019-05-01 | 2019-06-01 | 2019-07-01 | 2019-08-01 | 2019-09-01 | 2019-10-01 | 2019-11-01 | 2019-12-01 | 2020-01-01 | 2020-02-01 |
---|---|---|---|---|---|---|---|---|---|---|---|---|
vs10000005 | 2.00 | 0.00 | 3.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 1.00 | 0.00 | 0.00 |
vs10000621 | 6.00 | 17.00 | 19.00 | 20.00 | 17.00 | 5.00 | 2.00 | 18.00 | 18.00 | 21.00 | 16.00 | 10.00 |
vs10000627 | 0.00 | 0.00 | 0.00 | 0.00 | 2.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 |
vs10000716 | 0.00 | 0.00 | 0.00 | 0.00 | 14.00 | 19.00 | 24.00 | 12.00 | 30.00 | 15.00 | 12.00 | 5.00 |
vs10000743 | 1.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 |
復(fù)購(gòu)率分析
復(fù)購(gòu)率的定義是在某時(shí)間窗口內(nèi)消費(fèi)兩次及以上的用戶在總消費(fèi)用戶中占比邀层。這里的時(shí)間窗口是月,如果一個(gè)用戶在同一天下了兩筆訂單遂庄,這里也將他算作復(fù)購(gòu)用戶寥院。
消費(fèi)兩次及以上記為1,消費(fèi)一次記為0涛目,沒(méi)有消費(fèi)記為NaN秸谢。
pivoted_counts.transf=pivoted_counts.applymap(lambda x:1 if x>1 else np.NaN if x==0 else 0)
pivoted_counts.transf.head()
user_id | 2019-03-01 | 2019-04-01 | 2019-05-01 | 2019-06-01 | 2019-07-01 | 2019-08-01 | 2019-09-01 | 2019-10-01 | 2019-11-01 | 2019-12-01 | 2020-01-01 | 2020-02-01 |
---|---|---|---|---|---|---|---|---|---|---|---|---|
vs10000005 | 1.00 | nan | 1.00 | nan | nan | nan | nan | nan | nan | 0.00 | nan | nan |
vs10000621 | 1.00 | 1.00 | 1.00 | 1.00 | 1.00 | 1.00 | 1.00 | 1.00 | 1.00 | 1.00 | 1.00 | 1.00 |
vs10000627 | nan | nan | nan | nan | 1.00 | nan | nan | nan | nan | nan | nan | nan |
vs10000716 | nan | nan | nan | nan | 1.00 | 1.00 | 1.00 | 1.00 | 1.00 | 1.00 | 1.00 | 1.00 |
vs10000743 | 0.00 | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan |
month_counts_reorder_rate=pivoted_counts.transf.sum()/pivoted_counts.transf.count()
plt.plot(month_counts_reorder_rate)
plt.title('每月用戶復(fù)購(gòu)率圖')
plt.xlabel('時(shí)間(月)')
plt.ylabel('百分比')
說(shuō)明:3月至6月新用戶加入數(shù)量較少,拉高了復(fù)購(gòu)率霹肝。在大量新用戶加入并流失的8月的復(fù)購(gòu)率較低估蹄。而在后期,這時(shí)的用戶都是大浪淘沙剩下的老客沫换,復(fù)購(gòu)率繼續(xù)上升臭蚁。
a,b=plt.subplots(figsize=(10,6))
b.plot(pivoted_counts.transf.count())
b.plot(pivoted_counts.transf.sum())
legends=['消費(fèi)人數(shù)','二次消費(fèi)以上用戶人數(shù)']
b.legend(legends)
plt.title('每月消費(fèi)和二次消費(fèi)以上用戶人數(shù)')
plt.xlabel('時(shí)間(月)')
plt.ylabel('用戶數(shù)')
回購(gòu)率分析
回購(gòu)率是某一個(gè)時(shí)間窗口內(nèi)消費(fèi)的用戶,在下一個(gè)時(shí)間窗口仍舊消費(fèi)的占比讯赏。比如1月消費(fèi)用戶1000垮兑,他們中有300個(gè)2月依然消費(fèi),回購(gòu)率是30%待逞。
pivoted_amount=df.pivot_table(index='user_id',columns='month',values='order_amount',aggfunc='mean').fillna(0)
columns_month=df.month.dt.date.sort_values().unique()
pivoted_amount.columns=columns_month
pivoted_amount.head()
user_id | 2019-03-01 | 2019-04-01 | 2019-05-01 | 2019-06-01 | 2019-07-01 | 2019-08-01 | 2019-09-01 | 2019-10-01 | 2019-11-01 | 2019-12-01 | 2020-01-01 | 2020-02-01 |
---|---|---|---|---|---|---|---|---|---|---|---|---|
vs10000005 | 25.00 | 0.00 | 19.67 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 80.00 | 0.00 | 0.00 |
vs10000621 | 414.00 | 20.00 | 20.00 | 20.00 | 17.65 | 20.00 | 20.00 | 20.00 | 20.00 | 20.00 | 20.00 | 20.00 |
vs10000627 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 |
vs10000716 | 0.00 | 0.00 | 0.00 | 0.00 | 20.00 | 41.84 | 10.83 | 15.00 | 15.33 | 20.00 | 20.00 | 20.20 |
vs10000743 | 20.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 |
#統(tǒng)計(jì)會(huì)員用戶是否回購(gòu)
pivoted_purchase=pivoted_amount.applymap(lambda x:1 if x>1 else 0)
pivoted_purchase.head()
user_id | 2019-03-01 | 2019-04-01 | 2019-05-01 | 2019-06-01 | 2019-07-01 | 2019-08-01 | 2019-09-01 | 2019-10-01 | 2019-11-01 | 2019-12-01 | 2020-01-01 | 2020-02-01 |
---|---|---|---|---|---|---|---|---|---|---|---|---|
vs10000005 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 |
vs10000621 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
vs10000627 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
vs10000716 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
vs10000743 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
def purchase_return(data):
status = []
for i in range(11):
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 pd.Series(status)
pivoted_purchase_return = pivoted_purchase.apply(purchase_return,axis=1)
pivoted_purchase_return.columns=columns_month
pivoted_purchase_return .head()
user_id | 2019-03-01 | 2019-04-01 | 2019-05-01 | 2019-06-01 | 2019-07-01 | 2019-08-01 | 2019-09-01 | 2019-10-01 | 2019-11-01 | 2019-12-01 | 2020-01-01 | 2020-02-01 |
---|---|---|---|---|---|---|---|---|---|---|---|---|
vs10000005 | 0.00 | nan | 0.00 | nan | nan | nan | nan | nan | nan | 0.00 | nan | nan |
vs10000621 | 1.00 | 1.00 | 1.00 | 1.00 | 1.00 | 1.00 | 1.00 | 1.00 | 1.00 | 1.00 | 1.00 | nan |
vs10000627 | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan |
vs10000716 | nan | nan | nan | nan | 1.00 | 1.00 | 1.00 | 1.00 | 1.00 | 1.00 | 1.00 | nan |
vs10000743 | 0.00 | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan |
pivoted_purchase_return_rate=pivoted_purchase_return.sum()/pivoted_purchase_return.count()
plt.plot(pivoted_purchase_return_rate)
plt.title('12個(gè)月內(nèi)用戶回購(gòu)率圖')
plt.xlabel('時(shí)間(月)')
plt.ylabel('百分比')
plt.xticks(rotation=90)
a,b=plt.subplots(figsize=(10,6))
b.plot(pivoted_purchase_return.count())
b.plot(pivoted_purchase_return.sum())
legends=['每月消費(fèi)人數(shù)','每月回購(gòu)人數(shù)']
b.legend(legends)
plt.title('每月消費(fèi)和每月回購(gòu)人數(shù)')
plt.xlabel('時(shí)間(月)')
plt.ylabel('用戶數(shù)')
a,b=plt.subplots(figsize=(10,6))
b.plot(pivoted_purchase_return_rate)
b.plot(month_counts_reorder_rate)
legends=['每月回購(gòu)率','每月復(fù)購(gòu)率']
b.legend(legends)
plt.title('每月回購(gòu)率和每月復(fù)購(gòu)率')
plt.xlabel('時(shí)間(月)')
plt.ylabel('百分比')
說(shuō)明:大體上甥角,每月用戶的復(fù)購(gòu)率高于回購(gòu)率,波動(dòng)性也較強(qiáng)识樱。新用戶的回購(gòu)率在30%左右嗤无,和老客差異不大。
數(shù)據(jù)分析-用戶行為中層分析
RFM分層
user_rfm=df.pivot_table(index='user_id',values=['order_dt','order_products','order_amount'],aggfunc={'order_dt':'max','order_products':'count','order_amount':'sum'})
user_rfm.head()
user_id | order_amount | order_dt | order_products |
---|---|---|---|
vs10000005 | 189 | 2019-12-27 | 6 |
vs10000621 | 5704 | 2020-02-28 | 169 |
vs10000627 | 0 | 2019-07-23 | 2 |
vs10000716 | 2616 | 2020-02-28 | 131 |
vs10000743 | 20 | 2019-03-15 | 1 |
user_rfm['period']=(user_rfm.order_dt.max()-user_rfm.order_dt)/np.timedelta64(1,'D')
user_rfm=user_rfm.rename(columns={'period':'R','order_products':'F','order_amount':'M'})
user_rfm.head()
user_id | M | order_dt | F | R |
---|---|---|---|---|
vs10000005 | 189 | 2019-12-27 | 6 | 63.00 |
vs10000621 | 5704 | 2020-02-28 | 169 | 0.00 |
vs10000627 | 0 | 2019-07-23 | 2 | 220.00 |
vs10000716 | 2616 | 2020-02-28 | 131 | 0.00 |
vs10000743 | 20 | 2019-03-15 | 1 | 350.00 |
#定義分層函數(shù)
def rfm_func(x):
level=x.apply(lambda x:'1' if x>=0 else '0')
label=level.R+level.F+level.M
d={'111':'高價(jià)值客戶','011':'重點(diǎn)保持客戶',
'101':'重點(diǎn)發(fā)展客戶','001':'重點(diǎn)挽留客戶',
'110':'一般價(jià)值客戶','010':'一般保持客戶',
'100':'一般發(fā)展客戶','000':'潛在客戶'}
result=d[label]
return result
user_rfm['label']=user_rfm[['R','F','M']].apply( lambda x:x-x.mean()).apply(rfm_func,axis=1)
user_rfm.head()
user_id | M | order_dt | F | R | label |
---|---|---|---|---|---|
vs10000005 | 189 | 2019-12-27 | 6 | 63.00 | 重點(diǎn)挽留客戶 |
vs10000621 | 5704 | 2020-02-28 | 169 | 0.00 | 重點(diǎn)保持客戶 |
vs10000627 | 0 | 2019-07-23 | 2 | 220.00 | 一般發(fā)展客戶 |
vs10000716 | 2616 | 2020-02-28 | 131 | 0.00 | 重點(diǎn)保持客戶 |
vs10000743 | 20 | 2019-03-15 | 1 | 350.00 | 一般發(fā)展客戶 |
user_rfm.groupby('label').count()
label | M | order_dt | F | R |
---|---|---|---|---|
一般保持客戶 | 3 | 3 | 3 | 3 |
一般發(fā)展客戶 | 146 | 146 | 146 | 146 |
潛在客戶 | 63 | 63 | 63 | 63 |
重點(diǎn)保持客戶 | 24 | 24 | 24 | 24 |
重點(diǎn)發(fā)展客戶 | 2 | 2 | 2 | 2 |
重點(diǎn)挽留客戶 | 2 | 2 | 2 | 2 |
高價(jià)值客戶 | 7 | 7 | 7 | 7 |
user_rfm.groupby('label').sum()
label | M | F | R |
---|---|---|---|
一般保持客戶 | 352 | 34 | 98.00 |
一般發(fā)展客戶 | 2653 | 272 | 28793.00 |
潛在客戶 | 1723 | 125 | 6377.00 |
重點(diǎn)保持客戶 | 32494 | 1416 | 846.00 |
重點(diǎn)發(fā)展客戶 | 2091 | 5 | 575.00 |
重點(diǎn)挽留客戶 | 2919 | 9 | 165.00 |
高價(jià)值客戶 | 3856 | 152 | 1429.00 |
from matplotlib import font_manager as fm #字體管理器
from matplotlib import cm#
proptease = fm.FontProperties()
proptease.set_size('medium')
labelindex =user_rfm.groupby('label').count().index
labelvalues =user_rfm.groupby('label')['M'].count().tolist()
s = pd.Series(labelvalues, index=labelindex )
labels = s.index
sizes = s.values
explode = (0,0,0,0,0.1,0.1,0.2) # only "explode" the 1st slice
fig, axes = plt.subplots(1,2,figsize=(10,6))
ax1,ax2 = axes.ravel()#結(jié)合ravel()函數(shù)列出所有子圖
colors = cm.rainbow(np.arange(len(sizes))/len(sizes))# # 隨機(jī)生成顏色
# patches:餅片怜庸。texts:分類(lèi)標(biāo)簽的文本列表当犯。autotexts:百分比部分的文本列表
patches, texts, autotexts = ax1.pie(sizes, labels=labels, autopct='%1.0f%%',explode=explode,
shadow=False, startangle=170, colors=colors, labeldistance=1.2,pctdistance=1.05, radius=0.4)
ax1.axis('equal')#將餅圖顯示為正圓形
plt.setp(texts, fontproperties=proptease)
# 設(shè)置百分比文本樣式
for i in autotexts:
i.set_size('large')
ax1.set_title('用戶分層結(jié)構(gòu)餅狀圖', loc='center')
ax2.axis('off')#關(guān)閉所有坐標(biāo)軸線、刻度標(biāo)記和標(biāo)簽
ax2.legend(patches, labels, loc='center left',fontsize=10)
plt.tight_layout()#tight_layout會(huì)自動(dòng)調(diào)整子圖參數(shù)割疾,使之填充整個(gè)圖像區(qū)域
分析:從用戶分層結(jié)果可知嚎卫,一般發(fā)展客戶占了較大的比重,為59%宏榕,潛在客戶排第二位拓诸,占比26%。
總分層分析
按照用戶的消費(fèi)行為麻昼,簡(jiǎn)單劃分成幾個(gè)維度:新用戶奠支、活躍用戶、不活躍用戶抚芦、回流用戶倍谜。
新用戶(new)的定義是第一次消費(fèi)迈螟。
活躍用戶(active)即老客,在某一個(gè)時(shí)間窗口內(nèi)有過(guò)消費(fèi)尔崔。
不活躍用戶(unactive)則是時(shí)間窗口內(nèi)沒(méi)有消費(fèi)過(guò)的老客答毫。
回流用戶(return)是在上一個(gè)窗口中沒(méi)有消費(fèi),而在當(dāng)前時(shí)間窗口內(nèi)有過(guò)消費(fèi)季春。
以上的時(shí)間窗口都是按月統(tǒng)計(jì)洗搂。
def active_status(data):
status = []
for i in range(12):
#若本月沒(méi)有消費(fèi)
if data[i] == 0:
if len(status) > 0:
if status[i-1] == 'unreg': #未注冊(cè)
status.append('unreg')
else:
status.append('unactive')
else:
status.append('unreg')
#若本月有消費(fèi)
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( lambda x:active_status(x),axis=1)
pivoted_purchase_status.columns=columns_month
pivoted_purchase_status .head()
user_id | 2019-03-01 | 2019-04-01 | 2019-05-01 | 2019-06-01 | 2019-07-01 | 2019-08-01 | 2019-09-01 | 2019-10-01 | 2019-11-01 | 2019-12-01 | 2020-01-01 | 2020-02-01 |
---|---|---|---|---|---|---|---|---|---|---|---|---|
vs10000005 | new | unactive | return | unactive | unactive | unactive | unactive | unactive | unactive | return | unactive | unactive |
vs10000621 | new | active | active | active | active | active | active | active | active | active | active | active |
vs10000627 | unreg | unreg | unreg | unreg | unreg | unreg | unreg | unreg | unreg | unreg | unreg | unreg |
vs10000716 | unreg | unreg | unreg | unreg | new | active | active | active | active | active | active | active |
vs10000743 | new | unactive | unactive | unactive | unactive | unactive | unactive | unactive | unactive | unactive | unactive | unactive |
pivoted_status_counts=pivoted_purchase_status.replace('unreg',np.NaN).apply(lambda x:pd.value_counts(x))
pivoted_status_counts
2019-03-01 | 2019-04-01 | 2019-05-01 | 2019-06-01 | 2019-07-01 | 2019-08-01 | 2019-09-01 | 2019-10-01 | 2019-11-01 | 2019-12-01 | 2020-01-01 | 2020-02-01 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
active | nan | 7.00 | 9 | 16.00 | 20.00 | 18.00 | 11 | 12 | 15 | 14 | 16 | 10 |
new | 13.00 | 2.00 | 8 | 9.00 | 17.00 | 17.00 | 10 | 9 | 6 | 7 | 7 | 1 |
return | nan | nan | 1 | nan | nan | nan | 4 | 5 | 1 | 4 | 2 | 3 |
unactive | nan | 6.00 | 5 | 7.00 | 12.00 | 31.00 | 51 | 59 | 69 | 73 | 80 | 92 |
plt.plot(pivoted_status_counts.T)
plt.title('每月各種用戶類(lèi)型占比折線圖')
plt.legend(pivoted_status_counts.index)
plt.xlabel('時(shí)間(月)')
plt.ylabel('用戶數(shù)')
分析:黑色的不活躍用戶占了較大的比重。紅色的活躍用戶較穩(wěn)定鹤盒,其與紫色的回流用戶相加大抵是本月消費(fèi)人數(shù)蚕脏。
回流用戶及活躍用戶分析
return_rate=pivoted_status_counts.apply(lambda x:x/x.sum(),axis=1)
plt.plot(return_rate.loc[['active','return'],].T)
plt.title('每月活躍用戶、回流用戶占比')
plt.xlabel('時(shí)間(月)')
plt.ylabel('百分?jǐn)?shù)')
plt.xticks(rotation=90)
說(shuō)明:結(jié)合回流用戶和活躍用戶看侦锯,在后期的消費(fèi)用戶中驼鞭,70%是回流用戶,30%是活躍用戶尺碰,整體質(zhì)量還好挣棕。
數(shù)據(jù)分析-用戶質(zhì)量分析
總質(zhì)量分析
user_amount=df.groupby('user_id').order_amount.sum().sort_values().reset_index()
user_amount['amount_cumsum']=user_amount.order_amount.cumsum()
user_amount.tail()
user_id | order_amount | amount_cumsum | |
---|---|---|---|
242 | vs10000716 | 2616 | 29735 |
243 | vs10000775 | 2730 | 32465 |
244 | vs30026748 | 3296 | 35761 |
245 | vs30029475 | 4623 | 40384 |
246 | vs10000621 | 5704 | 46088 |
amount_total=user_amount.amount_cumsum.max()
user_amount['prop'] = user_amount.amount_cumsum.apply(lambda x:x/amount_total)
plt.plot(user_amount.prop )
plt.title('用戶累計(jì)貢獻(xiàn)金額百分比')
plt.xlabel('人數(shù)')
plt.ylabel('百分?jǐn)?shù)')
說(shuō)明:此次數(shù)據(jù)集用戶總共247人,可見(jiàn)其中47人(約占總?cè)藬?shù)的19%)貢獻(xiàn)了超過(guò)80%的銷(xiāo)售金額亲桥。
數(shù)據(jù)分析-用戶生命周期分析
第一生命周期
#各會(huì)員首次洛心、最后一次消費(fèi)時(shí)間間隔
order_dt_min=df.groupby('user_id').order_dt.min()
order_dt_max=df.groupby('user_id').order_dt.max()
life_time=(order_dt_max-order_dt_min).reset_index()
life_time.head()
user_id | order_dt | |
---|---|---|
0 | vs10000005 | 273 days |
1 | vs10000621 | 351 days |
2 | vs10000627 | 1 days |
3 | vs10000716 | 238 days |
4 | vs10000743 | 0 days |
life_time.describe()
order_dt | |
---|---|
count | 247 |
mean | 32 days 03:59:01.700404 |
std | 73 days 19:15:10.251372 |
min | 0 days 00:00:00 |
25% | 0 days 00:00:00 |
50% | 1 days 00:00:00 |
75% | 13 days 00:00:00 |
max | 351 days 00:00:00 |
分析:由描述可知,所有用戶的平均生命周期是32天题篷,中位數(shù)是1天词身,即存在50%的客戶首次消費(fèi)即最后一次消費(fèi)。
最大值351天番枚,即本數(shù)據(jù)集的總天數(shù)法严,說(shuō)明存在從開(kāi)始到最后都消費(fèi)的高質(zhì)量用戶。
((order_dt_max-order_dt_min)/np.timedelta64(1,'D')).hist(bins=15)
plt.title('用戶生命周期直方圖')
plt.xlabel('天數(shù)')
plt.ylabel('人數(shù)')
消費(fèi)兩次以上的用戶生命周期
life_time['life_time']=life_time.order_dt/np.timedelta64(1,'D')
life_time[life_time.life_time>0].life_time.hist(bins=15)#排除僅消費(fèi)一次的客戶
plt.title('二次消費(fèi)以上用戶生命周期直方圖')
plt.xlabel('天數(shù)')
plt.ylabel('人數(shù)')
life_time[life_time.life_time>0].life_time.describe()
count 155.00
mean 51.26
std 87.84
min 1.00
25% 2.00
50% 7.00
75% 53.50
max 351.00
Name: life_time, dtype: float64
分析:二次消費(fèi)以上用戶生命周期為51天葫笼,略高于總體深啤。從策略上看,用戶首次消費(fèi)后應(yīng)該引導(dǎo)其再次消費(fèi)路星。
數(shù)據(jù)分析-用戶留存率分析
#留存率指用戶在第一次消費(fèi)后溯街,有多少比率進(jìn)行第二次消費(fèi)。和回流率的區(qū)別是留存傾向于計(jì)算第一次消費(fèi)洋丐,并且有多個(gè)時(shí)間窗口呈昔。
user_purchase_retention=pd.merge(left=df,right=order_dt_min.reset_index(),how='inner',on='user_id',suffixes=('','_min'))
user_purchase_retention['date_diff']=(user_purchase_retention.order_dt-user_purchase_retention.order_dt_min)/np.timedelta64(1,'D')
bin=[0,30,60,90,120,150,180,365]
user_purchase_retention['date_diff_bin']=pd.cut(user_purchase_retention['date_diff'],bins=bin)
user_purchase_retention.head(10)
user_id | order_dt | order_products | order_amount | month | order_dt_min | date_diff | date_diff_bin |
---|---|---|---|---|---|---|---|
vs30033073 | 2020-01-17 | 1 | 20 | 2020-01-01 | 2019-09-23 | 116.00 | (90, 120] |
vs30033073 | 2019-11-29 | 2 | 20 | 2019-11-01 | 2019-09-23 | 67.00 | (60, 90] |
vs30033073 | 2019-11-13 | 2 | 20 | 2019-11-01 | 2019-09-23 | 51.00 | (30, 60] |
vs30033073 | 2019-12-24 | 2 | 20 | 2019-12-01 | 2019-09-23 | 92.00 | (90, 120] |
vs30033073 | 2019-10-29 | 2 | 20 | 2019-10-01 | 2019-09-23 | 36.00 | (30, 60] |
vs30033073 | 2020-01-07 | 2 | 20 | 2020-01-01 | 2019-09-23 | 106.00 | (90, 120] |
vs30033073 | 2019-12-09 | 2 | 20 | 2019-12-01 | 2019-09-23 | 77.00 | (60, 90] |
vs30033073 | 2020-01-06 | 1 | 20 | 2020-01-01 | 2019-09-23 | 105.00 | (90, 120] |
vs30033073 | 2019-11-01 | 2 | 20 | 2019-11-01 | 2019-09-23 | 39.00 | (30, 60] |
vs30033073 | 2019-10-21 | 2 | 20 | 2019-10-01 | 2019-09-23 | 28.00 | (0, 30] |
pivoted_retention=user_purchase_retention.pivot_table(index='user_id',columns='date_diff_bin',values='order_amount',aggfunc=sum,dropna=False)
pivoted_retention.head()
user_id | (0,30] | (30,60] | (60,90] | (90,120] | (120,150] | (150,180] | (180,365] |
---|---|---|---|---|---|---|---|
vs10000005 | nan | 59 | nan | nan | nan | nan | 80 |
vs10000621 | 240 | 300 | 420 | 400 | 200 | 40 | 1700 |
vs10000627 | 0 | nan | nan | nan | nan | nan | nan |
vs10000716 | 280 | 795 | 240 | 220 | 440 | 280 | 341 |
vs10000743 | nan | nan | nan | nan | nan | nan | nan |
pivoted_retention.mean()
date_diff_bin
(0, 30] 52.70
(30, 60] 148.62
(60, 90] 171.52
(90, 120] 307.59
(120, 150] 112.90
(150, 180] 111.60
(180, 365] 700.36
dtype: float64
pivoted_retention.transf=pivoted_retention.fillna(0).applymap(lambda x:1 if x>0 else 0)
(pivoted_retention.transf.sum()/pivoted_retention.transf.count()).plot.bar()
plt.title('各時(shí)間段的用戶留存率')
plt.xlabel('時(shí)間跨度(天)')
plt.ylabel('百分?jǐn)?shù)')
分析:第一個(gè)月的留存率約超過(guò)17.5%,第二個(gè)月下降至15%,之后幾個(gè)月穩(wěn)定在6%左右,說(shuō)明后面幾個(gè)月流失率較大 友绝。
數(shù)據(jù)分析-決策分析
平均購(gòu)買(mǎi)周期:用戶兩次消費(fèi)行為的時(shí)間間隔堤尾。
def diff(group):
d=group.date_diff.shift(-1)-group.date_diff
return d
last_diff=user_purchase_retention.sort_values("order_dt").reset_index().groupby('user_id').apply(diff)
last_diff.head(10)
user_id
vs10000005 31 0.00
34 42.00
158 1.00
160 0.00
161 230.00
1715 nan
vs10000621 2 0.00
3 11.00
22 1.00
26 1.00
Name: date_diff, dtype: float64
last_diff.describe()
count 1766.00
mean 4.50
std 14.03
min 0.00
25% 1.00
50% 1.00
75% 4.00
max 230.00
Name: date_diff, dtype: float64
說(shuō)明:可知用戶的平均消費(fèi)間隔時(shí)間是4.5天。想要召回用戶九榔,在4.5天左右的消費(fèi)間隔是比較好的。
last_diff.hist(bins=15)
plt.title('用戶平均購(gòu)買(mǎi)周期直方圖')
plt.xlabel('時(shí)間跨度(天)')
plt.ylabel('百分?jǐn)?shù)')
說(shuō)明:典型的長(zhǎng)尾分布,大部分用戶的消費(fèi)間隔比較短哲泊。