數(shù)據(jù)分析項(xiàng)目——電商平臺(tái)用戶畫像分析

pre:數(shù)據(jù)集導(dǎo)入及說明

# 導(dǎo)入數(shù)據(jù)集
df = pd.read_excel("order_data.xlsx")
# 導(dǎo)入用戶詳情數(shù)據(jù)集
df_user = pd.read_excel("user_data.xlsx")

包括用戶行為數(shù)據(jù)和用戶基本信息數(shù)據(jù):

  • 用戶行為數(shù)據(jù)(用戶id,行為類型[購買、瀏覽、收藏、加購],商品id,商品種類,行為日期),共258179條
  • 用戶基本信息數(shù)據(jù)(用戶id,性別,年齡,城市,省份,婚姻情況,教育程度,工作等),共222條。
  • 時(shí)間跨度:2014-11-18 到 2014-12-18

分析思路

  • 基于用戶粒度:對用戶按照某種規(guī)則打標(biāo),便于精準(zhǔn)式營銷
  • 基于群體粒度:分析一個(gè)月在該平臺(tái)活躍的用戶整體情況
    整個(gè)分析思路如下圖:


    基于用戶粒度分析.png

    基于群體粒度分析.png

一、數(shù)據(jù)預(yù)處理

重復(fù)值處理
缺失值處理
數(shù)據(jù)格式處理:
日期格式的轉(zhuǎn)換 astype()

1、重復(fù)值處理

查看有無重復(fù)值:首先看使用df.info查看各個(gè)字段的記錄數(shù),再看去除重復(fù)值后的數(shù)量。以此判斷有無重復(fù)數(shù)據(jù)。
去重重復(fù)值可以使用函數(shù)drop_duplicates()

2、數(shù)據(jù)格式轉(zhuǎn)換

通過df.info查看數(shù)據(jù)格式

df.info()
#結(jié)果
 #   Column         Non-Null Count   Dtype 
---  ------         --------------   ----- 
 0   user_id        258179 non-null  int64 
 1   item_id        258179 non-null  int64 
 2   behavior_type  258179 non-null  int64 
 3   item_category  258179 non-null  int64 
 4   time           258179 non-null  object

看到time是object類型的,不適合處理。同時(shí)我們一般將數(shù)據(jù)分為日期和時(shí)間格式,因此對其進(jìn)行拆分處理。

  • 處理1:將time拆分為兩個(gè)字段,一個(gè)是日期,一個(gè)是時(shí)間。方便我們打標(biāo)。
  • 處理2:轉(zhuǎn)換格式。
    日期格式,可進(jìn)行日期運(yùn)算。時(shí)間轉(zhuǎn)換為整型,可進(jìn)行分類。
  • 使用的方法:series的str屬性(可以類比hql中的substr函數(shù),對其進(jìn)行切割),to_datetime函數(shù),astype函數(shù)(類比hql中的cast函數(shù))

為各個(gè)時(shí)段打標(biāo),將時(shí)段分為'凌晨'、'上午'、'中午'、'下午'、'晚上'
知識(shí)點(diǎn):pd.cut函數(shù),區(qū)間分割

df['hour'] = pd.cut(df.time, bins=[-1, 5, 10, 13, 18, 23],labels=['凌晨','上午','中午','下午','晚上'])
日期處理結(jié)果.png

3、空值的處理

查看空值,并計(jì)算數(shù)量??梢钥吹讲o空值。

df.isnull().sum()
#返回
user_id          0
item_id          0
behavior_type    0
item_category    0
time             0
dtype: int64

二、用戶消費(fèi)習(xí)慣分析

  • 用戶瀏覽活躍時(shí)間段:該用戶喜歡在哪個(gè)時(shí)間段活躍?
  • 用戶購物活躍時(shí)間段:該用戶喜歡在哪個(gè)時(shí)間段購物?

1、用戶瀏覽/購物活躍時(shí)間段

在訂單表中按照(用戶,時(shí)段)分組,取每個(gè)時(shí)段的記錄數(shù)(訂單數(shù)):

# 修改列名item_id為hour_counts
time_browse.rename(columns={'item_id':'hour_counts'},inplace=True)
# 統(tǒng)計(jì)每個(gè)用戶瀏覽次數(shù)最多的時(shí)刻
time_browse_max = time_browse.groupby(['user_id']).hour_counts.max().reset_index()
# 進(jìn)行關(guān)聯(lián)
time_browse = pd.merge(time_browse, time_browse_max, how='inner', on=['user_id','hour')
# 選取各用戶瀏覽次數(shù)最多的時(shí)刻,如有并列,用逗號(hào)連接
time_browse_hour = time_browse.loc[:,'hour'].groupby(time_browse['user_id']).agg(lambda x:','.join(x)).reset_index()

這里的操作流程與hive-sql類似,我們需要先把max算出來,再去關(guān)聯(lián)。
將生成的標(biāo)簽加入標(biāo)簽表:


用戶瀏覽活躍時(shí)間.png

同理,可統(tǒng)計(jì)出用戶購買的活躍時(shí)間段,在此不贅述,僅展示結(jié)果


用戶購物活躍時(shí)間.png

2、用戶最喜歡的類目

分析用戶最喜歡的類目,從而便于我們?yōu)槠溥M(jìn)行推薦。

# 先獲取需要的數(shù)據(jù)集
df_browse = df.loc[df['behavior_type']==1,['user_id','item_id','item_category']]
# 計(jì)算每個(gè)類目的出現(xiàn)次數(shù)
df_cate_browse = df_browse.groupby(['user_id','item_category']).item_id.count().reset_index()
df_cate_browse.rename(columns={'item_id':'cate_counts'},inplace=True)
# 按照user_id計(jì)算出現(xiàn)頻次最高的類目
df_cate_browse_max = df_cate_browse.groupby('user_id').cate_counts.max().reset_index()
# 關(guān)聯(lián)每個(gè)用戶的最頻繁訪問類目
df_cate_browse = pd.merge(df_cate_browse,df_cate_browse_max, how='inner',on=['user_id','cate_counts'])
# 可能存在瀏覽次數(shù)相同的類目,對其進(jìn)行合并,首先對類型進(jìn)行轉(zhuǎn)換
df_cate_browse['item_category'] = df_cate_browse['item_category'].astype(str)
df_cate_browse = df_cate_browse.loc[:,'item_category'].\
 groupby(df_cate_browse.user_id).agg(lambda x:','.join(x)).reset_index()
# 將其加入用戶標(biāo)簽表
labels = pd.merge(labels, df_cate_browse, how='left',on='user_id')
labels.rename(columns={'item_category':'cate_most_browse'},inplace=True)

最終得到標(biāo)簽表:


各用戶最喜歡類目.png

三、RFM分析

  • 用戶近30天活躍天數(shù)(活躍:有瀏覽、收藏、加購、購物四種行為之一)
  • 用戶最近一次購物距今天數(shù):判斷用戶最近是否活躍
  • 用戶最近兩次消費(fèi)間隔時(shí)間:判斷用戶的消費(fèi)頻率

1、用戶近30天行為分析

通過分析用戶分析最近的行為,來判斷該用戶是否活躍、流失

# 用戶近30天的購買次數(shù)
df_counts_30_buy = df[df.behavior_type==4].groupby('user_id').item_id.count().reset_index()
# 加入標(biāo)簽表
labels = pd.merge(labels,df_counts_30_buy,how='left',on='user_id')
labels.rename(columns={'item_id':'counts_30_buy'},inplace=True)
用戶近30天的購買次數(shù).png

分析近30天的活躍天數(shù),只要有瀏覽、收藏、加購和購物四種行為之一就認(rèn)為是活躍。

# nunique表示不同日期的天數(shù),去重計(jì)數(shù)
counts_30_active = df.groupby('user_id')['date'].nunique()
# 加入標(biāo)簽表
labels = pd.merge(labels,counts_30_active,how='left',on='user_id')
labels.rename(columns={'date':'counts_30_active'},inplace=True)

結(jié)果如下:


用戶近30天活躍天數(shù).png

我們可以通過查看所有用戶30天活躍天數(shù)的分布情況,來確認(rèn)一個(gè)分類的標(biāo)準(zhǔn),判斷某個(gè)用戶是否活躍。
用戶30天活躍天數(shù)分布圖如圖:


用戶30天活躍天數(shù)分布情況.png

總體上看,訪問天數(shù)多的訪客比訪問天數(shù)少的訪客數(shù)量多,且以20次左右為拐點(diǎn),因此定義訪問天數(shù)小于20次的為低活躍,訪問天數(shù)大于等于20次的定義為高活躍。此定義只是從用戶的分布角度出發(fā),工作中當(dāng)從業(yè)務(wù)出發(fā)定義是否活躍。
labels['buy_active_level'] = '高'
labels.loc[labels['counts_30_buy']<=19,'buy_active_level'] = '低'

同理,可分析用戶近7天的行為,包括其購物次數(shù)和活躍天數(shù)。
與上述操作類似,展示結(jié)果:


用戶近7天行為分析.png

2、最后一次行為距今天數(shù)

明確今天的日期,在本項(xiàng)目中,“今天”指“2014-12-19”,然后統(tǒng)計(jì)訂單表中用戶某種行為的最大日期與當(dāng)前日期的差值。
使用的函數(shù)是:datetime.strptime: new datetime parsed from a string (like time.strptime()) ,將字符串轉(zhuǎn)為date格式,以方便我們做日期運(yùn)算

days_buy = df[df['behavior_type']==4].groupby('user_id')['date'].max().apply(lambda x:(datetime.strptime('2014-12-19','%Y-%m-%d')-x).days)
#加入標(biāo)簽表
labels = pd.merge(labels,days_buy,how='left',on='user_id')
labels.rename(columns={'date':'days_buy'},inplace=True)

結(jié)果如圖:


用戶最后一次行為距今天數(shù).png

3、最后兩次購買行為間隔天數(shù)

使用日期的diff函數(shù)

# 首先對user_id和date進(jìn)行分組去重
df_interval_buy = df[df.behavior_type==4].groupby(['user_id','date']).item_id.count().reset_index()
# 然后對date降序排列,對其進(jìn)行差分,去空后保留第一行
df_interval_buy = df_interval_buy.groupby('user_id').date.apply(lambda x: x.sort_values().diff(1).dropna().head(1)).reset_index()
df_interval_buy['date'] = df_interval_buy['date'].apply(lambda x: x.days)
df_interval_buy.drop('level_1',axis=1,inplace=True)
df_interval_buy.rename({'date':'interval_buy'},inplace=True)
# 將其加入標(biāo)簽
labels = pd.merge(labels,df_interval_buy,how='left',on='user_id')
labels.head()

返回結(jié)果


用戶最后兩次購買行為間隔天數(shù)png

4、RFM分組

RFM分組是指按照最近一次消費(fèi) (Recency)、消費(fèi)頻率 (Frequency)和消費(fèi)金額(Monetary)進(jìn)行分組
最近一次消費(fèi),我們按照最后一次購物距今的天數(shù)進(jìn)行分組,同樣是觀看用戶的一個(gè)分布情況,然后看如何進(jìn)行分類。
消費(fèi)頻率,這里放寬要求,按照用戶的30天活躍天數(shù)進(jìn)行分類
消費(fèi)金額,本次不涉及金額的統(tǒng)計(jì)。
因此,我們可以根據(jù)活躍度分類和最近一次消費(fèi)將用戶劃分為四類:

  • 最近一次消費(fèi)距今天數(shù)(近)活躍度(高):重要價(jià)值客戶
  • 最近一次消費(fèi)距今天數(shù)(遠(yuǎn))活躍度(高):重要喚回客戶。歷史活躍度比較高但是最近沒買,說明存在流失的可能,要喚回他。
  • 最近一次消費(fèi)距今天數(shù)(近)活躍度(低):重要深耕客戶。最近購買了,但是活躍度不是很高。是我們要努力留住的客戶。
  • 最近一次消費(fèi)距今天數(shù)(遠(yuǎn))活躍度(低):即將流失客戶。歷史活躍度比較低且最近沒購買,可能用戶就要跑路了。
    首先看一下最近一次購物距今天數(shù)用戶的分布情況,看一下怎么分類。
last_buy_days = labels['days_buy'].value_counts().sort_index()
# 圖形繪制
plt.figure(figsize=(16,9))
last_buy_days.plot(title='最后一次購買距今天數(shù)與人數(shù)的關(guān)系',fontsize=18)
plt.ylabel('購買人數(shù)',fontsize=14)
plt.xlabel('距今天數(shù)',fontsize=14)

結(jié)果如圖


最后一次消費(fèi)距今天數(shù)分布情況.png

可以看到在第8天前后,用戶有明顯的分層,因此按照8天對其進(jìn)行劃分,最后一次消費(fèi)距今天數(shù)小于8天的,認(rèn)為最近有消費(fèi),大于8天的認(rèn)為最近無消費(fèi)

labels['buy_days_level'] = '高'
labels.loc[labels['days_buy']>8,'buy_days_level'] = '低'
#利用series的字符串屬性對值進(jìn)行拼接
labels['rfm_value'] = labels['buy_active_level'].str.cat(labels['buy_days_level'])
#自定義函數(shù)
def trans_value(x):
    if x == '高高':  ## 高活躍且最近購買
        return '重要價(jià)值客戶' 
    elif x == '低高':  ## 低活躍且最近購買(要繼續(xù)保持,所以要深耕)
        return '重要深耕客戶'
    elif x == '高低':   ##高度活躍但是最近沒購買,要喚回
        return '重要喚回客戶'
    else:            ##不活躍且最近沒有購買
        return '即將流失客戶'
labels['rfm'] = labels['rfm_value'].apply(trans_value)

返回結(jié)果:


用戶RF分層.png

通過value_counts查看每個(gè)值的出現(xiàn)次數(shù):

labels['rfm'].value_counts()
#返回
重要深耕客戶    114
重要價(jià)值客戶     67
即將流失客戶     40
重要喚回客戶      1

四、潛在購物行為分析

  • 是否瀏覽未下單
  • 是否加購未下單
    提取bahavior=1或者behavior=4的數(shù)據(jù),根據(jù)用戶id、商品id以及用戶行為來進(jìn)行分組,統(tǒng)計(jì)每個(gè)用戶的瀏覽情況和購買情況,每一個(gè)用戶對于每一件商品,如果瀏覽了但是未購買,則將其記為1。
    該標(biāo)簽基于的粒度是(用戶,商品),若用戶對某一商品瀏覽未下單,可相應(yīng)地進(jìn)行運(yùn)營策略的投放。
    下面的方法使用了數(shù)據(jù)透視表,數(shù)據(jù)透視表可以實(shí)現(xiàn)類似于列轉(zhuǎn)行的功能,將原來的數(shù)據(jù)變?yōu)榫S度,如在下列的方法中,我們將behavior_type變?yōu)榱司S度。
#提取瀏覽和購買的行為數(shù)據(jù)
df_browse_buy = df.loc[(df.behavior_type==1) | (df.behavior_type==4),['user_id','item_id','behavior_type','time']]
#使用數(shù)據(jù)透視表的方法打標(biāo)瀏覽未購買的行為
df_browse_buy.head()
browse_not_buy = pd.pivot_table(df_browse_buy,index=['user_id','item_id'], columns=['behavior_type'],values=['time'],aggfunc=['count'])

上述返回的結(jié)果值是:


1628926422.png

如果值為空,說明無相應(yīng)的行為,對瀏覽未購買的數(shù)據(jù)記錄進(jìn)行打標(biāo)
以上的步驟到商品粒度,下面對用戶進(jìn)行統(tǒng)計(jì),即只要用戶有瀏覽未下單的行為就對其進(jìn)行打標(biāo)

browse_not_buy = browse_not_buy.groupby('user_id').browse_not_buy.sum().reset_index()
labels = pd.merge(labels, browse_not_buy,how='left',on='user_id')

返回的結(jié)果如圖:


用戶瀏覽未購買分析.png

加購未下單同上述步驟

五、用戶的基本屬性分析

分析平臺(tái)用戶的年齡、學(xué)歷、性別、城市、職業(yè)、婚姻情況等,以便于我們?nèi)シ治鑫覀兊牡湫陀脩羰鞘裁础?/p>

1、性別

user_sex = df.groupby('gender').user_id.count()
# autopct設(shè)置顯示百分比,explode 表示各項(xiàng)距離圓心n個(gè)半徑
user_sex.plot.pie(y="user_id",figsize=(10,5),explode=[0.01,0.01],autopct='%1.1f%%',title="性別分布圖")
用戶性別比例.png

從上圖可以看出,平臺(tái)用戶中男性居多,女性較少。

2、年齡

值的分層可以使用pd.cut函數(shù)

# 用戶的年齡分布
bins = [0,20,25,30,35,40,45,50,55,200]
labels =["(0-20]","(20-25]","(25-30]","(30-35]","(35-40]","(40-45]","(45-50]","(50-55]","55歲以上"]
df['age_group'] = pd.cut(df.age, bins=bins, labels=labels)
# 繪制柱狀圖
age_group = df.groupby('age_group').user_id.count()
age_group.plot.bar(figsize=(10,5),x='age_group',y='user_id',title='用戶年齡分布',rot=0)
用戶年齡分布.png

從年齡分布圖中,可以看出平臺(tái)的用戶以25歲-40歲的用戶居多。青年人和中老年用戶較少。

3、地域分布

# 地域分布
province_df = df.groupby('province').user_id.count().reset_index().sort_values(by='user_id',ascending=True)
province_df.plot.barh(figsize=(10,5),x='province',y='user_id',legend=False)
# 根據(jù)城市排序
city_df = df.groupby('city').user_id.count().reset_index().sort_values(by='user_id',ascending=True)
city_df.plot.barh(x='city', y='user_id',legend=False)

返回結(jié)果如下圖,從結(jié)果中可以看到來自北上廣深的用戶占絕大部分比例。


省份分布.png

城市分布.png

4、婚姻

從婚姻分布情況中可以看到,平臺(tái)用戶中有超過60%的用戶為已婚。


婚姻分布.png

5、學(xué)歷

使用該平臺(tái)的用戶大部分擁有大學(xué)及以上的學(xué)歷


學(xué)歷分布.png

6、職業(yè)

使用該平臺(tái)的用戶大部分為互聯(lián)網(wǎng)從業(yè)人群


職業(yè)分布.png

六、用戶購物活躍分析

6.1 用戶購物時(shí)間

首先查看這一個(gè)月的時(shí)間跨度用戶每天的購物情況:


每天下單用戶數(shù).png

從上圖可以看出,該平臺(tái)每天的下單用戶數(shù)比較平穩(wěn),有一些周期性因素在其中,可能是每周周中和周末的購物情況不同。同時(shí),注意到12.12這一天購物用戶激增,可能是12.12購物節(jié)的因素。

再分析下用戶喜歡在周幾下單,哪個(gè)時(shí)間下單


購物日期分布.png

購物時(shí)間分布.png

從圖中我們可以看到用戶的喜歡的購物時(shí)間:周五,晚上9點(diǎn)。上午購物的人數(shù)都比較少,主要集中在下午和晚上。

6.2 下單用戶分層

通過用戶的下單情況,我們可以對每周的下單用戶進(jìn)行分層,將其分為活躍用戶、不活躍用戶和回流用戶。

  • 活躍用戶:上周消費(fèi),本周也消費(fèi)
  • 回流用戶:上周沒消費(fèi),本周消費(fèi)
  • 不活躍用戶:上周沒消費(fèi),本周沒消費(fèi)
    首先使用date中的weekofyear函數(shù)判斷當(dāng)前日期是本年的第幾周,然后根據(jù)上一周和本周的活躍情況對用戶進(jìn)行分層。判斷分層的代碼如下:
def active_status(data):
    status = []
    for i in range(5):
        # 本周有活躍
        if data[i+47] ==1:
            if len(status) > 0:
                if status[i-1] == 'unactive':
                    status.append('return')
                else:
                    status.append('active')
            else:
                status.append('active')
        # 本周不活躍
        else:
            status.append('unactive')

最終結(jié)果


用戶活躍分層.png

通過面積圖看一下每周不同類型用戶的比例情況:


不同類型用戶比例.png

從圖中可以看到,每周活躍的用戶數(shù)比較平穩(wěn)

6.3每周復(fù)購率分析

復(fù)購率:一周內(nèi)購買多次(>1)的用戶占總用戶的比例


每周復(fù)購率.png

從中可以看到,5周的復(fù)購用戶都在50%以上,47周和51周的復(fù)購率較低,可能是因?yàn)閿?shù)據(jù)不完整的原因。

7基于品類的分析

7.1 用戶最喜歡品類分析

用戶最喜歡購買的品類?
用戶最多收藏的品類?


用戶購物最多品類TOP5.png

用戶收藏最多品類TOP5.png

從結(jié)果可見,用戶最喜歡購買的品類前五名是6344、12189、5232、1863和4370,用戶收藏最多的品類是13230、5894、1863、6513和5027。

7.2 各商品的瀏覽/購物轉(zhuǎn)換率

轉(zhuǎn)換率=瀏覽該商品的用戶數(shù)/購買該商品的用戶數(shù)
最終結(jié)果如圖:


各品類轉(zhuǎn)換率.png

查看轉(zhuǎn)換率的分布情況:


轉(zhuǎn)換率情況.png

由于數(shù)據(jù)原因,存在一人瀏覽一人購買的情況,所以有部分的轉(zhuǎn)換率為100%。除去此部分?jǐn)?shù)據(jù),大部分的商品轉(zhuǎn)換率在0.5以下。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容