一形病、數(shù)據(jù)集介紹
該數(shù)據(jù)集是跨國數(shù)據(jù)集,包含2010年12月12日至2011年12月9日期間發(fā)生的所有在英國注冊的非商店在線零售業(yè)務(wù)的交易霞幅。該公司主要銷售禮品漠吻,并且大部分客戶是批發(fā)商。
二司恳、字段介紹
InvoiceNo: 發(fā)票號碼途乃,每筆交易分配唯一的6位整數(shù),而退貨訂單的代碼以字母'c'開頭扔傅。
StockCode: 產(chǎn)品代碼耍共,每個不同的產(chǎn)品分配唯一的5位整數(shù)。
Description: 產(chǎn)品描述猎塞,對每件產(chǎn)品的簡略描述划提。
Quantity: 產(chǎn)品數(shù)量,每筆交易的每件產(chǎn)品的數(shù)量邢享。
InvoiceDate: 發(fā)票日期和時間鹏往,每筆交易發(fā)生的日期和時間。
UnitPrice: 單價(英鎊)骇塘,單位產(chǎn)品價格伊履。
CustomerID:顧客號碼,每個客戶分配唯一的5位整數(shù)款违。
Country: 國家的名字唐瀑,每個客戶所在國家/地區(qū)的名稱。
三插爹、分析目的
通過分析銷售數(shù)據(jù)來了解在線零售業(yè)務(wù)的消費情況哄辣,分析用戶消費數(shù)據(jù)分析用戶消費行為。
分析問題:
- 商店消費情況
- 每月成交金額
- 每月銷售金額
- 每月消費人數(shù)
- 每月訂單數(shù)量
- 每月消費產(chǎn)品數(shù)量
- 每月客單價
- 消費國家分布
- 下單時間分布
- 每月退款產(chǎn)品數(shù)
- 每月退款金額
- 每月退款率
- 用戶消費行為
- 用戶消費次數(shù)赠尾、用戶消費金額力穗、用戶購買產(chǎn)品數(shù)量
- 消費次數(shù)與消費金額關(guān)系
- 用戶購買周期
- 新用戶、活躍用戶气嫁、不活躍用戶当窗、回流用戶、回流率
- 復(fù)購率和回購率
- RFM
四寸宵、分析內(nèi)容
載入庫和獲取數(shù)據(jù)
# 載入庫
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
# 設(shè)置中文編碼和負號的正常顯示
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus']=False
# 導(dǎo)入數(shù)據(jù)
df = pd.read_csv('data.csv', encoding='ISO-8859-1')
df.head()
df.info()
用戶ID部分缺失崖面,無法通過其他信息填充元咙,因此后期清洗將用戶ID缺失記錄刪除。
df.describe()
# 將產(chǎn)品數(shù)量為負數(shù)的記錄數(shù)與退款訂單的記錄數(shù)進行對比
df[df['Quantity']<0].count() == df['InvoiceNo'].str.startswith('C').sum()
部分產(chǎn)品數(shù)量是負數(shù)巫员,經(jīng)過驗證是退款訂單的產(chǎn)品數(shù)為負數(shù)
數(shù)據(jù)清洗和處理
# 刪除用戶ID缺失的記錄
df = df[df['CustomerID'].notnull()].copy()
# 數(shù)據(jù)類型轉(zhuǎn)換
df['InvoiceDate'] = pd.to_datetime(df['InvoiceDate'])
df['CustomerID'] = df['CustomerID'].astype('O')
# 計算時間變量
df['Month'] = df['InvoiceDate'].values.astype('datetime64[M]')
df['Day'] = df['InvoiceDate'].dt.day
df['Dayofweek'] = df['InvoiceDate'].dt.dayofweek
df['Hour'] = df['InvoiceDate'].dt.hour
# 計算價格
df['Price'] = df['Quantity'] * df['UnitPrice']
探索性數(shù)據(jù)分析
商店銷售情況分析
原數(shù)據(jù)集粒度為訂購商品庶香,轉(zhuǎn)換為訂單粒度,看一下數(shù)據(jù)情況
# 訂單描述性統(tǒng)計分析
df.groupby('InvoiceNo')[['Quantity','Price']].sum().describe()
因為零售商大部分客戶是批發(fā)商简识,用戶每筆訂單平均產(chǎn)品數(shù)量和平均金額波動大赶掖,中位數(shù)和75分位數(shù)相差挺大,說明部分批發(fā)商批發(fā)數(shù)量大财异。
每月成交金額
# 商店消費情況繪圖函數(shù)
def store_plot(data, xlab, ylab, title):
plt.figure(figsize=(10,5))
plt.plot(data)
plt.xlabel(xlab)
plt.ylabel(ylab)
plt.title(title)
# 每月成交金額,包含退款訂單的金額
store_plot(data=df[df['Quantity']>0].groupby('Month')['price'].sum(),
xlab='月份',
ylab='成交金額',
title='每月成交金額')
從2010年12月至2011年11月月成交金額總體呈現(xiàn)上漲趨勢唱遭,從2010年8月開始高漲戳寸,可能是因為公司主要銷售的產(chǎn)品包括禮品,而后半年國外有各種節(jié)日導(dǎo)致對禮品需求大增拷泽,也有可能是接近年底有各種促銷活動疫鹊,2011年2月和2011年4月都有一個明顯的下降,暫時不清楚具體原因司致。
每月銷售金額
# 每月銷售金額拆吆,成交金額-退款金額
store_plot(data=df.groupby('Month')['Price'].sum(),
xlab='月份',
ylab='銷售金額',
title='每月銷售金額')
月銷售金額跟月成交金額趨勢非常相似,可以看到2011年1月銷售金額較成交金額有較大差異脂矫,可能是由于這個月的退款金額比較大枣耀。
每月消費人數(shù)
# 每月消費人數(shù)
store_plot(data=df[df['Quantity']>0].groupby('Month')['CustomerID'].nunique(),
xlab='月份',
ylab='消費人數(shù)',
title='每月消費人數(shù)')
每月訂單數(shù)量
# 每月訂單數(shù)量
store_plot(data=df[df['Quantity']>0].groupby('Month')['InvoiceNo'].nunique(),
xlab='月份',
ylab='訂單數(shù)量',
title='每月訂單數(shù)量')
每月消費產(chǎn)品數(shù)量
# 每月銷售產(chǎn)品數(shù)量
store_plot(data=df[df['Quantity']>0].groupby('Month')['Quantity'].sum(),
xlab='月份',
ylab='銷售產(chǎn)品數(shù)量',
title='每月銷售產(chǎn)品數(shù)量')
每月客單價
# 每月客單價
store_plot(data=df[df['Quantity']>0].groupby('Month')['Price'].sum()/df[df['Quantity']>0].groupby('Month')['InvoiceNo'].nunique(),
xlab='月份',
ylab='客單價',
title='每月客單價')
- 月訂單數(shù)量、月消費人數(shù)和銷售產(chǎn)品數(shù)量趨勢都跟月成交金額趨勢相似庭再,每月客單價趨勢與月成交金額趨勢差別比較大
- 2011年1月較2010年12月消費人數(shù)和訂單數(shù)量下降捞奕,銷售產(chǎn)品數(shù)量和客單價上升,尤其是客單價很高拄轻,因此2011年1月與2010年12月成交金額持平主要原因是1月客單價遠遠高于12月客單價
- 2011年2月和2011年4月的成交金額環(huán)比減少是由于消費人數(shù)颅围、訂單數(shù)量、銷售產(chǎn)品數(shù)量和客單價都減少的原因
- 2011年5月至2011年10月總體呈上升趨勢原因是消費人數(shù)恨搓、訂單數(shù)量院促、銷售產(chǎn)品數(shù)量和客單價總體持平或上升
- 2011年11月成交金額大漲主要是因為購買用戶數(shù)、訂單數(shù)和購買產(chǎn)品數(shù)增多斧抱,這個月客戶購買的產(chǎn)品價格比較低
- 由于數(shù)據(jù)集中只有成交信息常拓、產(chǎn)品信息、地區(qū)和時間辉浦,具體上升或下降的原因沒辦法具體判斷墩邀,推測可能是年底的促銷活動或節(jié)日引起的
消費國家分布
# 國家用戶數(shù)量分布
plt.figure(figsize=(12,8))
df[df['Quantity']>0].groupby('Country')['CustomerID'].nunique().sort_values(ascending=True).plot.barh()
plt.xlabel('用戶數(shù)量')
plt.ylabel('國家')
plt.title('不同國家用戶數(shù)量')
# 國家訂單數(shù)量分布
plt.figure(figsize=(12,8))
df[df['Quantity']>0].groupby('Country')['InvoiceNo'].nunique().sort_values(ascending=True).plot.barh()
plt.xlabel('訂單數(shù)量')
plt.ylabel('國家')
plt.title('不同國家訂單數(shù)量')
# 國家成交金額分布
plt.figure(figsize=(12,8))
df[df['Quantity']>0].groupby('Country')['Price'].sum().sort_values(ascending=True).plot.barh()
plt.xlabel('成交金額')
plt.ylabel('國家')
plt.title('不同國家成交金額')
- 因為該公司在英國,因此可以看到客戶數(shù)量盏浙、訂單數(shù)量和成交金額英國都遠遠超過其他國家眉睹,英國是客戶來源的主要國家荔茬,屬于重要價值國家。
- 除英國外竹海,德國和法國在用戶數(shù)量慕蔚、訂單數(shù)量和成交金額方面都屬于前5,屬于重點維持國家斋配。
- 荷蘭孔飒、愛爾蘭和澳大利亞雖然用戶數(shù)量和訂單數(shù)量少,但是成交金額位于前6艰争,這三個國家的客單價比較高坏瞄,屬于重點發(fā)展國家。
- 重點維持國家和重點發(fā)展國家可以進行適當(dāng)推廣甩卓、完善物流服務(wù)等等鸠匀。
下單時間分布
# 星期
plt.figure(figsize=(12,8))
df[df['Quantity']>0].groupby('Dayofweek')['InvoiceNo'].nunique().plot.bar()
plt.xticks(range(6),['周一','周二','周三','周四','周五','周日'], rotation=0)
plt.xlabel('星期')
plt.ylabel('訂單數(shù)')
plt.title('訂單數(shù)隨星期變化')
絕大多數(shù)訂單在周一至周四完成。
# 小時
plt.figure(figsize=(12,8))
df[df['Quantity']>0].groupby('Hour')['InvoiceNo'].nunique().plot()
plt.xlabel('小時')
plt.ylabel('訂單數(shù)')
plt.title('訂單數(shù)隨小時變化')
訂單集中在上午10點至下午3點逾柿,中午12點是高峰期缀棍,這段時間內(nèi)注意維持好網(wǎng)站的穩(wěn)定性。
每月退款訂單數(shù)
# 每月退款訂單數(shù)量
store_plot(data=df[df['Quantity']<0].groupby('Month')['InvoiceNo'].nunique(),
xlab='月份',
ylab='退款訂單數(shù)量',
title='每月退款訂單數(shù)量')
每月退款訂單數(shù)量2010年12月至2011年10月圍繞280上下波動机错,略微呈上漲趨勢爬范,雖然2011年11月訂單數(shù)量非常大,但同時退款訂單數(shù)量也非常大弱匪。
每月退款金額
# 每月退款金額
store_plot(data=df[df['Quantity']<0].groupby('Month')['Price'].sum().abs(),
xlab='月份',
ylab='退款金額',
title='每月退款金額')
- 每月退款金額圍繞25000波動青瀑。
- 2011年1月退款訂單數(shù)量不大,因為客單價高萧诫,所以退款金額非常高狱窘,也印證了我們之前的猜測。
- 由于2011年11月客單價很低财搁,即使退款訂單很多蘸炸,退款金額也不大。
每月退款率
# 每月退款率
store_plot(data=df[df['Quantity']<0].groupby('Month')['InvoiceNo'].nunique()/df[df['Quantity']>0].groupby('Month')['InvoiceNo'].nunique(),
xlab='月份',
ylab='退款率',
title='每月退款率')
每月退款率呈下降趨勢尖奔,這是個不錯的現(xiàn)象搭儒。
用戶消費行為分析
用戶消費次數(shù)、用戶消費金額提茁、用戶購買產(chǎn)品數(shù)量
將數(shù)據(jù)集粒度轉(zhuǎn)換成用戶淹禾,看一下用戶消費行為。
df[df['Quantity']>0].groupby('CustomerID').agg({'InvoiceNo':'nunique',
'Quantity':'sum',
'Price':'sum'}).describe()
- 超過一半客戶至少消費了兩次茴扁,甚至有客戶消費了210次铃岔,屬于非常忠誠的用戶了。
- 因為大部分客戶是批發(fā)商,超過75%的客戶購買數(shù)量在100以上毁习。
- 用戶平均消費金額是2053元智嚷,標(biāo)準(zhǔn)差是8988元,用戶平均消費金額大于75分位數(shù)纺且,存在部分高額消費用戶盏道。
消費次數(shù)與消費金額關(guān)系
# 消費次數(shù)與消費金額關(guān)系
plt.figure(figsize=(12,8))
plt.scatter(x=df[df['Quantity']>0].groupby('CustomerID')['InvoiceNo'].nunique(),
y=df[df['Quantity']>0].groupby('CustomerID')['Price'].sum())
plt.xlabel('消費次數(shù)')
plt.ylabel('消費金額')
plt.title('消費次數(shù)與消費金額關(guān)系')
plt.savefig('消費次數(shù)與消費金額關(guān)系.jpeg')
消費次數(shù)和消費金額有較弱的相關(guān)性,用戶消費次數(shù)越大载碌,消費金額越大猜嘱,可以引導(dǎo)用戶多次消費,那么多長時間召回呢嫁艇?我們來看看用戶的消費間距朗伶。
用戶消費周期
# 用戶消費周期
purchase_time = df[df['Quantity']>0].groupby('CustomerID').apply(lambda x: x['InvoiceDate']-x['InvoiceDate'].shift()).dt.days
purchase_time.describe()
purchase_time[purchase_time>0].describe()
至少消費兩次的用戶有一半消費間隔在一個月內(nèi),75%消費間隔在兩個月內(nèi)步咪,可以在10天论皆、28天、58天三個時間點對用戶進行推送和提醒歧斟。
新用戶纯丸、活躍用戶偏形、不活躍用戶静袖、回流用戶、回流率
pivoted_amount = df[df['Quantity']>0].pivot_table(index='CustomerID',
columns='Month',
values='Price',
aggfunc='mean').fillna(0)
columns_month = df['Month'].sort_values().astype('str').unique()
pivoted_amount.columns = columns_month
pivoted_purchase = pivoted_amount.applymap(lambda x: 1 if x>0 else 0)
# 用戶分層
def active_status(data):
status = []
for i in range(13):
# 若本月沒有消費
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 pd.Series(status, index=columns_month)
pivoted_purchase_status = pivoted_purchase.apply(lambda x: active_status(x), axis=1)
purchase_status_counts = pivoted_purchase_status.replace('unreg',np.NaN).apply(lambda x:pd.value_counts(x))
purchase_status_counts.fillna(0).T.plot.area(figsize=(12,6))
plt.xticks(range(12), columns_month)
plt.title('用戶分層')
# 回流率
return_rate = purchase_status_counts.apply(lambda x:x / x.sum(), axis=1)
return_rate.loc['return'].plot(figsize=(12,6))
plt.xticks(range(1,13), columns_month)
plt.title('回流率')
在后期消費中新用戶占比減少俊扭,回流用戶和活躍用戶增多队橙,回流率一直在上漲,整體用戶質(zhì)量不錯萨惑。
復(fù)購率和回購率
# 復(fù)購率
pivoted_counts = df[df['Quantity']>0].pivot_table(index='CustomerID',
columns='Month',
values='InvoiceNo',
aggfunc='nunique').fillna(0)
columns_month = df['Month'].sort_values().astype('str').unique()
pivoted_counts.columns = columns_month
pivoted_counts_transf = pivoted_counts.applymap(lambda x: 1 if x>1 else np.NaN if x==0 else 0)
(pivoted_counts_transf.sum() / pivoted_counts_transf.count()).plot(figsize=(12,6))
plt.xticks(range(12), columns_month)
plt.title('復(fù)購率'
由于早期新用戶占比大捐康,前期復(fù)購率比后期復(fù)購率低,且后期復(fù)購率波動大庸蔼,但復(fù)購率基本在20%以上解总。
# 回購率
def purchase_return(data):
status = []
for i in range(12):
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, index=columns_month)
pivoted_purchase_return = pivoted_purchase.apply(purchase_return,axis=1)
(pivoted_purchase_return.sum() / pivoted_purchase_return.count()).plot(figsize=(12,6))
plt.xticks(range(12), columns_month)
plt.title('回購率')
用戶的回購率高于復(fù)購率,都大于30%姐仅,后期因為回流用戶增多花枫,這段時間老用戶的忠誠度表現(xiàn)較好,所以后期回購率較高掏膏。
RFM
# rfm
rfm = df[df['Quantity']>0].groupby('InvoiceNo').agg({'daydiff':'min',
'Quantity':'sum',
'Price':'sum'})
rfm.rename(columns={'daydiff':'R',
'Quantity':'F',
'Price':'M'},inplace=True)
def rfm_func(x):
level = x.apply(lambda x: '1' if x > 0 else '0')
label = level.R + level.F + level.M
d = {
'111':'重要價值客戶',
'011':'重要保持客戶',
'101':'重要挽留客戶',
'001':'重要發(fā)展客戶',
'110':'一般價值客戶',
'010':'一般保持客戶',
'100':'一般挽留客戶',
'000':'一般發(fā)展客戶'
}
result = d[label]
return result
rfm['label'] = rfm[['R','F','M']].apply(lambda x: x-x.median()).apply(rfm_func, axis=1)
rfm.groupby('label').sum()
rfm.groupby('label')['M'].count()
五劳翰、總結(jié)
- 從2011年5月開始成交金額總體上升芝此,11月達到高峰郁竟,成交金額主要受到消費人數(shù)、訂單數(shù)量和客單價的影響逻谦,但由于數(shù)據(jù)只包含部分成交數(shù)據(jù)沒有辦法得知上漲或下降的具體原因颖变,推測可能是年中以后節(jié)日增多導(dǎo)致禮品需求量增大或促銷活動引起生均。
- 英國是主要的客戶來源地區(qū)听想,而德國、法國疯特、荷蘭哗魂、愛爾蘭和澳大利亞成交金額表現(xiàn)不錯,可以嘗試拓展這些國家的市場漓雅;訂單下單時間高峰期主要在10點至15點录别,這段時間要維護好網(wǎng)站的穩(wěn)定。
- 退款訂單數(shù)略微呈上漲趨勢邻吞,2011年11月退款訂單數(shù)最高组题;退款金額總體持平,2011年1月退款金額高抱冷;退款率在下降崔列,這是個好現(xiàn)象。
- 多數(shù)用戶至少消費了兩次旺遮,由于大部分客戶是批發(fā)商赵讯,購買數(shù)量和金額較大;用戶消費次數(shù)越多耿眉,消費金額越大边翼,可以在半個月、一個月鸣剪、兩個月三個時間段對用戶進行召回组底,引導(dǎo)客戶進行多次消費。
- 活躍用戶比例和回流用戶比例隨時間增大筐骇,后期老用戶忠誠度較好债鸡,因此復(fù)購率和回購率表現(xiàn)不錯;可以通過RFM模型對用戶價值進行分類铛纬,不同價值用戶采取不同的業(yè)務(wù)決策厌均。