第一部分:數據類型處理
- 數據加載
- 字段含義:
- user_id:用戶ID
- order_dt:購買日期
- order_product:購買產品的數量
- order_amount:購買金額
- 字段含義:
- 觀察數據
- 查看數據的數據類型
- 數據中是否存儲在缺失值
- 將order_dt轉換成時間類型
- 查看數據的統計描述
- 在源數據中添加一列表示月份:astype('datetime64[M]')
df = pd.read_csv('./data/CDNOW_master.txt',header=None,sep='\s+',names=['user_id','order_dt','order_product','order_amount']) #sep='\s+' 分割間隔 一個或多個空格 df.head()
df.shape
(69659, 4)
#查看數據類型
df.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 69659 entries, 0 to 69658 Data columns (total 4 columns): user_id 69659 non-null int64 order_dt 69659 non-null int64 order_product 69659 non-null int64 order_amount 69659 non-null float64 dtypes: float64(1), int64(3) memory usage: 2.1 MB
#order_dt轉換成時間序列,且加一列為購買商品的月份
df['order_dt'] = pd.to_datetime(df['order_dt'],format="%Y%m%d")
df.head()

df['month'] = df['order_dt'].astype('datetime64[M]')
df.head()

df.describe() #對數據源中的數值型數據的描述
第二部分:按月數據分析
- 用戶每月花費的總金額
- 繪制曲線圖展示
- 所有用戶每月的產品購買量
- 所有用戶每月的消費總次數
- 統計每月的消費人數
#用戶每月花費的總金額
df.groupby(by='month')['order_amount'].sum()
month 1997-01-01 299060.17 1997-02-01 379590.03 1997-03-01 393155.27 1997-04-01 142824.49 1997-05-01 107933.30 1997-06-01 108395.87 1997-07-01 122078.88 1997-08-01 88367.69 1997-09-01 81948.80 1997-10-01 89780.77 1997-11-01 115448.64 1997-12-01 95577.35 1998-01-01 76756.78 1998-02-01 77096.96 1998-03-01 108970.15 1998-04-01 66231.52 1998-05-01 70989.66 1998-06-01 76109.30 Name: order_amount, dtype: float64
#繪制曲線圖展示
df.groupby(by='month')['order_amount'].sum().plot()

#所有用戶每月的產品購買量
df.groupby(by='month')['order_product'].sum()
month 1997-01-01 19416 1997-02-01 24921 1997-03-01 26159 1997-04-01 9729 1997-05-01 7275 1997-06-01 7301 1997-07-01 8131 1997-08-01 5851 1997-09-01 5729 1997-10-01 6203 1997-11-01 7812 1997-12-01 6418 1998-01-01 5278 1998-02-01 5340 1998-03-01 7431 1998-04-01 4697 1998-05-01 4903 1998-06-01 5287 Name: order_product, dtype: int64
#所有用戶每月的消費總次數
df.groupby(by='month')['user_id'].count()
month 1997-01-01 8928 1997-02-01 11272 1997-03-01 11598 1997-04-01 3781 1997-05-01 2895 1997-06-01 3054 1997-07-01 2942 1997-08-01 2320 1997-09-01 2296 1997-10-01 2562 1997-11-01 2750 1997-12-01 2504 1998-01-01 2032 1998-02-01 2026 1998-03-01 2793 1998-04-01 1878 1998-05-01 1985 1998-06-01 2043 Name: user_id, dtype: int64
#統計每月的消費人數
df.groupby(by='month')['user_id'].nunique()
month 1997-01-01 7846 1997-02-01 9633 1997-03-01 9524 1997-04-01 2822 1997-05-01 2214 1997-06-01 2339 1997-07-01 2180 1997-08-01 1772 1997-09-01 1739 1997-10-01 1839 1997-11-01 2028 1997-12-01 1864 1998-01-01 1537 1998-02-01 1551 1998-03-01 2060 1998-04-01 1437 1998-05-01 1488 1998-06-01 1506 Name: user_id, dtype: int64
第三部分:用戶個體消費數據分析
- 所有用戶消費總金額和消費總購買量的統計描述
- 各個用戶消費金額和消費產品數量的散點圖
- 各個用戶消費總金額的直方分布圖(消費金額在1000之內的分布)
- 各個用戶消費的總數量的直方分布圖(消費商品的數量在100次之內的分布)
#所有用戶消費總金額和消費總購買量的統計描述
df['order_product'].sum(),df['order_amount'].sum()
(167881, 2500315.6300000004)
#各個用戶消費金額和消費產品數量的散點圖
users_amount_s = df.groupby(by='user_id')['order_amount'].sum()
users_product_s = df.groupby(by='user_id')['order_product'].sum()
plt.scatter(users_amount_s,usea_product_s)
#各個用戶消費總金額的直方分布圖(消費金額在1000之內的分布)
#1.先將滿足要求的用戶的行數據找出,在做分組聚合
user_amount_1000_s = df.query('order_amount <= 1000').groupby(by='user_id')['order_amount'].sum()
user_amount_1000_s
#各個用戶消費的總數量的直方分布圖(消費商品的數量在100之內的分布)
df.query('order_product <= 100').groupby(by='user_id')['order_product'].sum()
#df有兩個常用方法 # - apply:可以作為df的運算工具,運算df的行或者列 # - applymap:針對df中每一個元素進行指定形式的運算
第四部分:用戶消費行為分析
- 用戶第一次消費的月份分布,和人數統計
- 繪制線形圖
- 用戶最后一次消費的時間分布,和人數統計
- 繪制線形圖
- 新老客戶的占比
- 消費一次為新用戶
- 消費多次為老用戶
- 分析出每一個用戶的第一個消費和最后一次消費的時間
- agg(['func1','func2']):對分組后的結果進行指定多種形式的聚合
- 分析出新老客戶的消費比例
- 分析出每一個用戶的第一個消費和最后一次消費的時間
- 用戶分層
- 分析得出每個用戶的總購買量和總消費金額and最近一次消費的時間的表格rfm
- RFM模型設計
- R表示客戶最近一次交易時間的間隔。
- /np.timedelta64(1,'D'):去除days
- F表示客戶購買商品的總數量,F值越大,表示客戶交易越頻繁,反之則表示客戶交易不夠活躍。
- M表示客戶交易的金額。M值越大,表示客戶價值越高,反之則表示客戶價值越低。
- 將R,F,M作用到rfm表中
- R表示客戶最近一次交易時間的間隔。
- 根據價值分層,將用戶分為:
- 重要價值客戶
- 重要保持客戶
- 重要挽留客戶
- 重要發展客戶
- 一般價值客戶
- 一般保持客戶
- 一般挽留客戶
- 一般發展客戶
- 使用已有的分層模型即可rfm_func
# 用戶第一次消費的月份分布,和人數統計
# 繪制線形圖
# 用戶最后一次消費的時間分布,和人數統計
# 繪制線形圖
df.groupby(by='user_id')['month'].min().value_counts()
1997-02-01 8476 1997-01-01 7846 1997-03-01 7248 Name: month, dtype: int64
df.groupby(by='user_id')['month'].max().value_counts()
1997-02-01 4912 1997-03-01 4478 1997-01-01 4192 1998-06-01 1506 1998-05-01 1042 1998-03-01 993 1998-04-01 769 1997-04-01 677 1997-12-01 620 1997-11-01 609 1998-02-01 550 1998-01-01 514 1997-06-01 499 1997-07-01 493 1997-05-01 480 1997-10-01 455 1997-09-01 397 1997-08-01 384 Name: month, dtype: int64
#新老客戶的占比
df_new_old = df.groupby(by='user_id')['order_dt'].agg(['min','max'])
(df_new_old['min'] == df_new_old['max']).value_counts()
True 12054 False 11516 dtype: int64
#分析得出每個用戶的總購買量和總消費金額and最近一次消費的時間的表格rfm
rfm = df.pivot_table(index='user_id',aggfunc={'order_product':'sum','order_amount':'sum','order_dt':'max'}) #采用透視操作
rfm.head()
rfm['R'] = (df['order_dt'].max() - rfm['order_dt'])/np.timedelta64(1,'D')
rfm = rfm[['order_amount','order_product','R']]
rfm.columns = ['M','F','R']
rfm.head()
#rfm分層算法
def rfm_func(x):
#存儲存儲的是三個字符串形式的0或者1
level = x.map(lambda x :'1' if x >= 0 else '0')
# M '0'
# F '0'
# R '1'
label = level['R'] + level.F + level.M
d = {
'111':'重要價值客戶',
'011':'重要保持客戶',
'101':'重要挽留客戶',
'001':'重要發展客戶',
'110':'一般價值客戶',
'010':'一般保持客戶',
'100':'一般挽留客戶',
'000':'一般發展客戶'
}
result = d[label]
return result
#df.apply(func):可以對df中的行或者列進行某種(func)形式的運算
rfm['label'] = rfm.apply(lambda x : x - x.mean(),axis=0).apply(rfm_func,axis = 1)
rfm.head()
第五部分:用戶的生命周期
- 將用戶划分為活躍用戶和其他用戶
- 統計每個用戶每個月的消費次數
- 統計每個用戶每個月是否消費,消費記錄為1否則記錄為0
- 知識點:DataFrame的apply和applymap的區別
- applymap:返回df
- 將函數做用於DataFrame中的所有元素(elements)
- apply:返回Series
- apply()將一個函數作用於DataFrame中的每個行或者列
- 知識點:DataFrame的apply和applymap的區別
- 將用戶按照每一個月份分成:
- unreg:觀望用戶(前兩月沒買,第三個月才第一次買,則用戶前兩個月為觀望用戶)
- unactive:首月購買后,后序月份沒有購買則在沒有購買的月份中該用戶的為非活躍用戶
- new:當前月就進行首次購買的用戶在當前月為新用戶
- active:連續月份購買的用戶在這些月中為活躍用戶
- return:購買之后間隔n月再次購買的第一個月份為該月份的回頭客
#統計每個用戶每個月的消費次數
df_purchase = df.pivot_table(index='user_id',values='order_dt',aggfunc='count',columns='month',fill_value=0) #columns='month' 對 values='order_dt'又做了一次划分
df_purchase.head()
#統計每個用戶每個月是否消費,消費記錄為1否則記錄為0
df_purchase = df_purchase.applymap(lambda x:1 if x > 0 else 0)
df_purchase.head()
#將df_purchase中的原始數據0和1修改為new,unactive......,返回新的df叫做df_purchase_new
#固定算法 修改參數即可用
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
pivoted_status = df_purchase.apply(active_status,axis = 1)
pivoted_status.head()
user_id 1 [new, unactive, unactive, unactive, unactive, ... 2 [new, unactive, unactive, unactive, unactive, ... 3 [new, unactive, return, active, unactive, unac... 4 [new, unactive, unactive, unactive, unactive, ... 5 [new, active, unactive, return, active, active... dtype: object
df_purchase_new = DataFrame(data=pivoted_status.tolist(),index=df_purchase.index,columns=df_purchase.columns)
df_purchase_new.head()
每月【不同活躍】用戶的計數
- purchase_status_ct = df_purchase_new.apply(lambda x : pd.value_counts(x)).fillna(0)
- 轉置進行最終結果的查看
df_purchase_new.apply(lambda x:pd.value_counts(x),axis=0).fillna(0).T
