背景:
用戶消費(fèi)行為分析學(xué)習(xí)材料
數(shù)據(jù):txt格式. 百度云 提取碼:9tkg
問(wèn)題引入點(diǎn):秦璐—如何七周成為數(shù)據(jù)分析師:用Python分析用戶消費(fèi)行為
思路整理分析:CDNow網(wǎng)站用戶消費(fèi)行為分析——Python篇
關(guān)鍵點(diǎn):
1.項(xiàng)目背景:分析CDNow網(wǎng)站的用戶購(gòu)買(mǎi)明細(xì)來(lái)分析該網(wǎng)站的用戶消費(fèi)行為,使運(yùn)營(yíng)部門(mén)在營(yíng)銷時(shí)更加具有針對(duì)性,從而節(jié)省成本,提升效率。
2.導(dǎo)入數(shù)據(jù)與清洗
導(dǎo)庫(kù):pandas 、numpy、matplotlib.pyplot、datetime
描述性統(tǒng)計(jì) df.describe() 數(shù)據(jù)信息(缺省值) df.info() 類型轉(zhuǎn)換
3.消費(fèi)行為特征
用戶總體消費(fèi)趨勢(shì)分析——月份
用戶消費(fèi)周期分析——用戶ID
購(gòu)買(mǎi)周期(按訂單),周期(按第一次&最后一次消費(fèi))
用戶分層——價(jià)值(RFM模型)/ 活躍程度(新用戶、活躍用戶、不活躍用戶、回流用戶)
用戶質(zhì)量分析 消費(fèi)時(shí)長(zhǎng),復(fù)購(gòu)率, 回購(gòu)率, 留存率,貢獻(xiàn)率
具體練習(xí)程序:
基本語(yǔ)法補(bǔ)充;https://www.cnblogs.com/nxld/p/6058591.html Python中的pandas模塊進(jìn)行數(shù)據(jù)分析
#導(dǎo)入常用的庫(kù)
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from datetime import datetime
% matplotlib inline
‘%’內(nèi)置的命令,jupyter專有的定義,比如在pycharm不常用到,inline意思是做圖之后可以在html頁(yè)面的單元格進(jìn)行顯示
plt.style.use('ggplot') #更改設(shè)計(jì)風(fēng)格,使用自帶的形式進(jìn)行美化,這是一個(gè)r語(yǔ)言的風(fēng)格
#導(dǎo)入源數(shù)據(jù)
columns = ['用戶ID','購(gòu)買(mǎi)日期','訂單商品數(shù)','訂單金額']
df = pd.read_table("D:/BaiduNetdiskDownload/CDNOW_master.txt",names = columns,sep = '\s+')
df.head()
如果不做數(shù)據(jù)清洗,很難進(jìn)行下一步的數(shù)據(jù)分析,為了進(jìn)行數(shù)據(jù)格式的轉(zhuǎn)化,pandas里面有三種比較常用的方法
- astype()強(qiáng)制轉(zhuǎn)化數(shù)據(jù)類型
帶有特殊符號(hào)的object是不能直接通過(guò)astype("flaot)方法進(jìn)行轉(zhuǎn)化的,如果數(shù)據(jù)是純凈的數(shù)據(jù),可以轉(zhuǎn)化為數(shù)字.astype基本也就是兩種用作,數(shù)字轉(zhuǎn)化為單純字符串,單純數(shù)字的字符串轉(zhuǎn)化為數(shù)字,含有其他的非數(shù)字的字符串是不能通過(guò)astype進(jìn)行轉(zhuǎn)化的 - 通過(guò)創(chuàng)建自定義的函數(shù)進(jìn)行數(shù)據(jù)轉(zhuǎn)化
例如: convert the string number to a float
_ 去除$ - 去除逗號(hào), - 轉(zhuǎn)化為浮點(diǎn)數(shù)類型.
//////////////////////////////////////////////////////////////////////
def convert_currency(var): new_value = var.replace(",","").replace("$","") return float(new_value) 又例如 .apply(lambda x: x.replace(",","").replace("$","")).astype("float64") 再如利用np.where() function 將Active 列轉(zhuǎn)化為布爾值。
- pandas提供的to_nueric()以及to_datetime() 使用pd.to_numeric可以將其它形式的數(shù)據(jù)轉(zhuǎn)換成整數(shù)型的數(shù)據(jù)
利用pd.to_datatime()將年月日進(jìn)行合并 pd.to_datetime(df[['Month', 'Day', 'Year']])
df.describe()

#索引,數(shù)據(jù)類型和內(nèi)存信息
df.info()

df.dtypes

# 將購(gòu)買(mǎi)日期列進(jìn)行數(shù)據(jù)類型轉(zhuǎn)換
df['購(gòu)買(mǎi)日期'] = pd.to_datetime(df.購(gòu)買(mǎi)日期,format = '%Y%m%d') #Y四位數(shù)的日期部分,y表示兩位數(shù)的日期部分
df['月份'] = df.購(gòu)買(mǎi)日期.values.astype('datetime64[M]')
df.head()

#解決中文顯示參數(shù)設(shè)置
plt.rcParams['font.sans-serif']=['SimHei'] #用來(lái)正常顯示中文標(biāo)簽
plt.rcParams['axes.unicode_minus'] = False #用來(lái)正常顯示負(fù)號(hào)
# 設(shè)置圖的大小,添加子圖
plt.figure(figsize=(25,15))
# 每月的總銷售額
plt.subplot(221)
df.groupby('月份')['訂單金額'].sum().plot(fontsize=24)
plt.title('總銷售額',fontsize=24)
#每月的消費(fèi)次數(shù)
plt.subplot(222)
df.groupby('月份')['購(gòu)買(mǎi)日期'].count().plot(fontsize=24)
plt.title('消費(fèi)次數(shù)',fontsize=24)
#每月的銷量
plt.subplot(223)
df.groupby('月份')['訂單商品數(shù)'].sum().plot(fontsize=24)
plt.title('總銷量',fontsize=24)
#每月的消費(fèi)人數(shù)
plt.subplot(224)
df.groupby('月份')['用戶ID'].apply(lambda x:len(x.unique())).plot(fontsize=24)
plt.title('消費(fèi)人數(shù)',fontsize=24)
plt.tight_layout() # 設(shè)置子圖的間距
plt.show()

# 根據(jù)用戶id進(jìn)行分組
group_user = df.groupby('用戶ID').sum()
group_user.describe()

#查詢條件:訂單金額 < 4000
group_user.query('訂單金額 < 4000').plot.scatter(x='訂單金額',y='訂單商品數(shù)')

group_user.訂單金額. plot.hist(bins = 20)
#bins = 20,就是分成20塊,最高金額是14000,每個(gè)項(xiàng)就是700

group_user.query("訂單金額< 800")["訂單金額"].plot.hist(bins=40)

group_user.query('訂單商品數(shù) < 100').訂單商品數(shù).hist(bins = 25)

#每個(gè)用戶的每次購(gòu)買(mǎi)時(shí)間間隔
order_diff = df.groupby('用戶ID').apply(lambda x:x['購(gòu)買(mǎi)日期'] - x['購(gòu)買(mǎi)日期'].shift())
order_diff.head(10)
[注]注意表的所選數(shù)據(jù)要一致 同步更新,in[*]好像是沒(méi)處理完,結(jié)果沒(méi)顯示出來(lái)。
shift 用法 https://www.cnblogs.com/iamxyq/p/6283334.html shift函數(shù)是對(duì)數(shù)據(jù)進(jìn)行移動(dòng)的操作
函數(shù)原型:DataFrame.shift(periods=1, freq=None, axis=0) 正值下移
參數(shù) periods:類型為int,表示移動(dòng)的幅度,可以是正數(shù),也可以是負(fù)數(shù),默認(rèn)值是1,1就表示移動(dòng)一次,注意這里移動(dòng)的都是數(shù)據(jù),而索引是不移動(dòng)的,移動(dòng)之后沒(méi)有對(duì)應(yīng)值的,就賦值為NaN。
freq: DateOffset, timedelta, or time rule string,可選參數(shù),默認(rèn)值為None,只適用于時(shí)間序列,如果這個(gè)參數(shù)存在,那么會(huì)按照參數(shù)值移動(dòng)時(shí)間索引,而數(shù)據(jù)值沒(méi)有發(fā)生變化。
axis:{0, 1, ‘index’, ‘columns’},表示移動(dòng)的方向,如果是0或者’index’表示上下移動(dòng),如果是1或者’columns’,則會(huì)左右移動(dòng)。

order_diff.describe()

plt.figure(figsize=(15,5))
plt.hist((order_diff / np.timedelta64(1, 'D')).dropna(), bins = 50)
plt.xlabel('消費(fèi)周期',fontsize=24)
plt.ylabel('頻數(shù)',fontsize=24)
plt.title('用戶消費(fèi)周期分布圖',fontsize=24)
dropna用法:如果是Series,則返回一個(gè)僅含非空數(shù)據(jù)和索引值的Series,默認(rèn)丟棄含有缺失值的行;處理DataFrame對(duì)象,默認(rèn)濾除所有包含NaN,傳入how=‘a(chǎn)ll’濾除全為NaN的行,傳入axis=1濾除列(0-行),傳入thresh=n保留至少有n個(gè)非NaN數(shù)據(jù)的行。
https://blog.csdn.net/weixin_38168620/article/details/79596798?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase
timedelta64其實(shí)就是能將時(shí)間轉(zhuǎn)換為是以年,月或者日,小時(shí)等為基礎(chǔ)單位。在已有的日期時(shí)間上可以與之加減運(yùn)算,較為方便,不需要自己將兩個(gè)運(yùn)算的時(shí)間轉(zhuǎn)換一致。

orderdt_min=df.groupby('用戶ID').購(gòu)買(mǎi)日期.min()#第一次消費(fèi)
orderdt_max=df.groupby('用戶ID').購(gòu)買(mǎi)日期.max()#最后一次消費(fèi)
id_ordercycle=orderdt_max-orderdt_min
id_ordercycle.head()

id_ordercycle.describe()

((orderdt_max-orderdt_min)/np.timedelta64(1,'D')).hist(bins=15)
因?yàn)閿?shù)據(jù)類型是timedelta時(shí)間,無(wú)法直接作出直方圖,所以先換算成數(shù)值。換算的方式直接除timedelta函數(shù)即可,np.timedelta64(1, ‘D’),D表示天,1表示1天,作為單位使用的。因?yàn)閙ax-min已經(jīng)表示為天了,兩者相除就是周期

#計(jì)算所有消費(fèi)過(guò)兩次以上的老客的生命周期
life_time = (orderdt_max - orderdt_min).reset_index()
life_time.head(10)

#用戶生命周期分布圖
plt.figure(figsize=(10,5))
life_time['life_time'] = life_time.購(gòu)買(mǎi)日期 / np.timedelta64(1,'D')
life_time[life_time.life_time > 0].life_time.hist(bins = 150, figsize = (15,10))
#判斷語(yǔ)句,篩選數(shù)據(jù)(life_time.hist,數(shù)據(jù)里還有user_id)

#去掉0天生命周期的用戶之后的用戶生命周期各描述值
life_time[life_time.life_time>0].購(gòu)買(mǎi)日期.describe()

參考《Pandas透視表(pivot_table)詳解》一文,鏈接地址:http://python.jobbole.com/81212/
pivot_table(data,values=None,
index=None,
columns=None,
aggfunc='mean',
fill_value=None,
margins=False,
dropna=True,
margins_name='All')
rfm = df.pivot_table(index = '用戶ID',
values = ['訂單金額','購(gòu)買(mǎi)日期','訂單商品數(shù)'],
aggfunc = {'訂單金額':'sum',
'購(gòu)買(mǎi)日期':'max',
'訂單商品數(shù)':'sum'})
rfm.head()

# 日期的最大值與當(dāng)前日期的差值為R
rfm['R'] = (rfm['購(gòu)買(mǎi)日期'].max() - rfm['購(gòu)買(mǎi)日期']) / np.timedelta64(1,'D')
rfm.rename(columns = {'訂單金額':'M',
'訂單商品數(shù)':'F'},
inplace=True)
rfm.head()

# 構(gòu)建rfm模型公式
def get_rfm(x):
level = x.apply(lambda x:'1' if x>=0 else '0')
label = level['R'] + level['F'] + level['M']
d = {'111':'重要價(jià)值客戶',
'011':'重要保持客戶',
'101':'重要挽留客戶',
'001':'重要發(fā)展客戶',
'110':'一般價(jià)值客戶',
'010':'一般保持客戶',
'100':'一般挽留客戶',
'000':'一般發(fā)展客戶'}
result = d[label]
return result
rfm['label'] = rfm[['R','F','M']].apply(lambda x:(x-x.mean()) / x.std()).apply(get_rfm,axis=1)# 先計(jì)算出平均值差值與std差的比值,再用自定義函數(shù)
rfm.head()

#求和
rfm.groupby('label').sum()

rfm.groupby('label').size().sort_values()
排序 http://www.itdecent.cn/p/bea8c73582e1

rfm.groupby('label').sum().sort_values(by ="M")

#將用戶消費(fèi)數(shù)據(jù)進(jìn)行數(shù)據(jù)透視:
#用戶活躍程度分層
#將用戶消費(fèi)數(shù)據(jù)進(jìn)行數(shù)據(jù)透視:
df1 = df.pivot_table(index = "用戶ID",
columns = "月份",
values = '購(gòu)買(mǎi)日期',
aggfunc = 'count').fillna(0)
df1.head()

1.dataframe和series中都有apply方法,dataframe中的apply方法需要指定axis參數(shù),是對(duì)一行或者一列進(jìn)行操作,比如求一列的最大值與最小值之差等;series中的apply方法與map方法一樣,都是作用于單個(gè)元素,所以不具有axis參數(shù);更不能求最大值與最小值之差,因?yàn)閍pply到的是單個(gè)元素,單個(gè)元素時(shí)沒(méi)有最大值、最小值一說(shuō)的;
2. dataframe中的apply()函數(shù)是自動(dòng)作用于每一列/行,不是單獨(dú)某一列或者某一行,否則就成了series了
3.series中的map和apply函數(shù)自動(dòng)作用于每一個(gè)元素,不是單獨(dú)的某個(gè)元素,否則直接指定元素進(jìn)行相應(yīng)操作好啦,不用map和apply函數(shù)了
https://www.cnblogs.com/ironan-liu/p/11458546.html
df2 = df1.applymap(lambda x:1 if x>0 else 0)
df2.tail()

#可得到一張不同用戶在不同月份的不同狀態(tài)(new=新、active=活躍、return=回流、unactive=流失),
# unreg相當(dāng)于未注冊(cè),指這個(gè)用戶在這個(gè)月及以前從未購(gòu)買(mǎi)過(guò)產(chǎn)品,主要為了統(tǒng)計(jì)起來(lái)更加方便而加進(jìn)去。
def active_status(data):
status=[]
for i in range(18): #共18個(gè)月
#若本月沒(méi)有消費(fèi)
if data[i]==0:
if len(status)>0:#前面某月消費(fèi)過(guò),是老客
if status[i-1]=='unreg':#前一個(gè)月不是首次消費(fèi),不是新客
status.append('unreg')#則本月也不是新客
else:
status.append('unactive')#前一個(gè)月是首次消費(fèi),屬于新客,則本月為不活躍用戶
else:
status.append('unreg')#前面某月沒(méi)有消費(fèi)過(guò),則本月也不是新客
#若本月消費(fèi)
else:
if len(status)==0:#前面沒(méi)有消費(fèi)過(guò)
status.append('new')#則為新客
else:#前面消費(fèi)過(guò)
if status[i-1] =='unactive':#前一個(gè)月沒(méi)有消費(fèi),是不活躍用戶
status.append('return')#本月為回流用戶
elif status[i-1]=='unreg':#前一個(gè)月沒(méi)有消費(fèi),不是新客
status.append('new')
else:#前一個(gè)月是首次消費(fèi)
status.append('active')#本月為活躍用戶
return status
indexs=df['月份'].sort_values().astype('str').unique()
df3=df2.apply(lambda x:pd.Series(active_status(x),index=indexs),axis=1)
u =df3.reset_index()
df3.head()

df4=df3.apply(lambda x:pd.value_counts(x)).fillna(0).T
df4

#把unreg替換成NaN,再用fillna(0)把空值填為0。然后轉(zhuǎn)置,把月份作為索引行,狀態(tài)作為列,得到如下的表
df4=df3.replace('unreg',np.NaN).apply(lambda x:pd.value_counts(x)).fillna(0).T
df4

u =df4.reset_index()# (in/re)set_ index 用法 https://blog.csdn.net/jingyi130705008/article/details/78162758
u.head()

#非堆積圖效果 stackplot https://blog.csdn.net/qq_35189715/article/details/96108580
labels = u[['active','new','return','unactive']].columns
plt.figure(figsize=(15,5))
plt.stackplot(u['index'].astype(str).apply(lambda x:x[:-3]), u['active'],u['new'],u['return'],u['unactive'], labels=labels)
plt.xlabel('月份')
plt.ylabel('消費(fèi)人數(shù)')
plt.title('每月的消費(fèi)人數(shù)')
plt.legend(loc = 'upper left');

python之matplotlib和pandas繪圖 1.https://blog.csdn.net/layman2016/article/details/79538889?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.nonecase&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.nonecase
2.https://blog.csdn.net/genome_denovo/article/details/78322628?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase
3.https://blog.csdn.net/qq_40195360/article/details/103710930
df5=df4.apply(lambda x:x/x.sum(),axis=1)#每一層用戶占總用戶的比例
df5

a = df.groupby('用戶ID')['購(gòu)買(mǎi)日期'].agg(['min','max']).reset_index()
#agg函數(shù)通常用于調(diào)用groupby()函數(shù)之后,對(duì)數(shù)據(jù)做一些聚合操作,包括sum,min,max以及其他一些聚合函數(shù),
# 通常在調(diào)用完agg函數(shù)后需要reset_index,因pandas會(huì)默認(rèn)將groupby()的列也做為index傳到結(jié)果中
a.head()

new_old = (a['min'] == a['max']).value_counts().values
plt.pie(x = new_old,
autopct = '%.1f%%',
shadow = True,
explode = [0.08,0],
textprops = {'fontsize' : 11})
plt.axis('equal')
plt.legend(['僅消費(fèi)一次','多次消費(fèi)'])

#每個(gè)用戶在每月的訂單數(shù)
#pivot_table透視表
pivoted_df=df.pivot_table(index='用戶ID',columns='月份',values='購(gòu)買(mǎi)日期',aggfunc='count').fillna(0)#某些用戶在某月沒(méi)有消費(fèi)過(guò),用nan表示,這里用0填充
pivoted_df.head()

#轉(zhuǎn)換:消費(fèi)2次以上記為1,消費(fèi)1次記為0,消費(fèi)0次記為NAN
#applymap針對(duì)dataframe所有數(shù)據(jù)
pivoted_df_transf=pivoted_df.applymap(lambda x: 1 if x>1 else np.nan if x==0 else 0)
#lambda 之后是該匿名函數(shù)的一個(gè)或多個(gè)參數(shù)(用英文逗號(hào)分隔),然后是一個(gè)英文冒號(hào) : 大于1是1,等于0是nan,其他是0
pivoted_df_transf.head()

#count統(tǒng)計(jì)所有非空數(shù)據(jù)個(gè)數(shù)表示總消費(fèi)用戶數(shù),sum計(jì)算非0數(shù)據(jù)的和表示消費(fèi)兩次以上的用戶數(shù)
df_duplicate =pd.DataFrame(pivoted_df_transf.sum()/pivoted_df_transf.count()).reset_index()
df_duplicate.columns = ['Date', 'DuplicatedRate']
df_duplicate['Date'] = df_duplicate.Date.astype(str).apply(lambda x:x[:-3])
plt.figure(figsize = (15,6))
plt.plot(df_duplicate.Date, df_duplicate.DuplicatedRate)
plt.xlabel('時(shí)間', fontsize=24)
plt.ylabel('復(fù)購(gòu)率',fontsize=24)
# plt.ylim(0,1)
plt.title('復(fù)購(gòu)率的變化',fontsize=24)

# unique()是以 數(shù)組形式(numpy.ndarray)返回列的所有唯一值(特征的所有唯一值)
# nunique() Return number of unique elements in the object.即返回的是唯一值的個(gè)數(shù)
#回購(gòu)率
#每個(gè)用戶每個(gè)月平均消費(fèi)金額
pivoted_money=df.pivot_table(index='用戶ID',columns='月份',values='訂單金額',
aggfunc='mean').fillna(0) # pd.pivot_table 參數(shù) http://www.itdecent.cn/p/d6782830fe62
columns_month=df.月份.sort_values().astype('str').unique()
pivoted_money.columns=columns_month
pivoted_money.head()

#將有消費(fèi)的記為1,沒(méi)有消費(fèi)的記為0
pivoted_purchase=pivoted_money.applymap(lambda x:1 if x>0 else 0)
pivoted_purchase.head()

# 判斷
def purchase_return(data):
status=[]
for i in range(17):
if data[i]==1:#當(dāng)月有消費(fèi)
if data[i+1]==1:#下月再次消費(fèi)
status.append(1) #就記為1 回購(gòu)
if data[i+1]==0:
status.append(0)
else:
status.append(np.nan)
status.append(np.nan)
return pd.Series(status, index=columns_month) #status
pivoted_purchase_return=pivoted_purchase.apply(purchase_return,axis=1) #axis=1表示計(jì)算方向在行的方向上,左右運(yùn)算
pivoted_purchase_return.head()

df_purchase = (pivoted_purchase_return.sum() / pivoted_purchase_return.count()).reset_index()
df_purchase.columns = ['Date', 'PurchaseRate']
df_purchase['Date'] = df_purchase.Date.astype(str).apply(lambda x:x[:-3])# [:-3]去掉倒數(shù)3個(gè),此處對(duì)應(yīng) -01
plt.figure(figsize = (15,5))
plt.plot(df_purchase.Date, df_purchase.PurchaseRate)
plt.xlabel('時(shí)間', fontsize=24)
plt.ylabel('回購(gòu)率', fontsize=24)
plt.title('回購(gòu)率的變化', fontsize=24)

#分析留存率
#新建一個(gè)對(duì)象,并增加用戶第一次消費(fèi)時(shí)間的列,merge將兩個(gè)dataframe合并
data_t=df[['用戶ID','購(gòu)買(mǎi)日期','訂單商品數(shù)','訂單金額']]
user_purchase_retention=pd.merge(left=data_t,right=orderdt_min.reset_index(),
how='inner',on='用戶ID',suffixes=('','_min'))#當(dāng)列沖突時(shí),即有多個(gè)列名稱相同時(shí),需要使用on=來(lái)指定哪一個(gè)列作為key,配合suffixes指定沖突列名;可以使用suffixes=自己指定后綴
#jupyter入門(mén)之pandas https://blog.csdn.net/weixin_42042680/article/details/80684415
user_purchase_retention.head(5)

#每一次消費(fèi)時(shí)間與第一次消費(fèi)時(shí)間間隔
user_purchase_retention['order_date_diff']=user_purchase_retention['購(gòu)買(mǎi)日期']-user_purchase_retention['購(gòu)買(mǎi)日期_min']
#將timedelta轉(zhuǎn)換為數(shù)值型
user_purchase_retention['date_diff']=user_purchase_retention.order_date_diff.apply(lambda x:x/np.timedelta64(1,'D'))
user_purchase_retention.head(5)

#將時(shí)間間隔分桶(0-3)(3-7)等
bin=[0,3,7,15,30,60,90,180,365]
user_purchase_retention['date_diff_bin']=pd.cut(user_purchase_retention.date_diff,bins=bin)
user_purchase_retention.head(10)

#用戶第一次消費(fèi)之后,后續(xù)各時(shí)間段的消費(fèi)總額
pivoted_retention=user_purchase_retention.pivot_table(index='用戶ID',
columns='date_diff_bin',values='訂單金額',aggfunc=sum,dropna=False)
pivoted_retention.head()

pivoted_retention.mean()#各時(shí)間段的平均消費(fèi)額

#1代表有消費(fèi),0代表沒(méi)有
pivoted_retention_trans=pivoted_retention.applymap(lambda x:1 if x>0 else 0)
pivoted_retention_trans

#每筆訂單離第一筆訂單的時(shí)間間隔
(pivoted_retention_trans.sum()/pivoted_retention_trans.count()).plot.bar(figsize=(10,5))
plt.xlabel('消費(fèi)時(shí)間間隔')
plt.title('留存率')

#先將用戶消費(fèi)金額按升序排列,逐行計(jì)算用戶累計(jì)金額,最后一行是總消費(fèi)金額
user_money=df.groupby('用戶ID').訂單金額.sum().sort_values().reset_index()
user_money['money_cumsum']=user_money.訂單金額.cumsum()
money_total=user_money.money_cumsum.max()#python cumsum函數(shù) 累加和 https://blog.csdn.net/banana1006034246/article/details/78841461
#轉(zhuǎn)行成百分比
user_money['prop']=user_money.apply(lambda x:x.money_cumsum/money_total,axis=1)#apply用在每個(gè)行上
user_money.tail()
user_money.prop.plot()
plt.xlabel('用戶ID', fontsize=24)
plt.ylabel('比率', fontsize=24)
plt.title('用戶累計(jì)銷售額貢獻(xiàn)比', fontsize=24);
