當前位置:首頁 > IT技術 > 編程語言 > 正文

實戰(zhàn)案例,手把手教你用 Python 構建電商用戶畫像
2022-02-14 14:17:58


大家好,本文以真實案為例手把手教你搭建電商系統(tǒng)的用戶畫像。

先來看該電商用戶畫像用到的標簽。

數(shù)據(jù)內(nèi)容包括user_id(用戶身份)、item_id(商品)、IDbehavior_type(用戶行為類型,包含點擊、收藏、加購物車、支付四種行為,分別用數(shù)字1、2、3、4表示)、user_geohash(地理位置)、item_category(品類ID,即商品所屬的品類)、Time(用戶行為發(fā)生的時間),其中user_id和item_id因為涉及隱私,做了脫敏處理,顯示的是數(shù)字編號。

下面是具體的代碼實現(xiàn)過程。

導入庫

本示例除了用到numpy、pandas、matplotlib,還用到其他一些模塊。

# 導入所需的庫
%matplotlib inline
import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
from datetime import datetime

參數(shù)說明如下。


  • %matplotlib inline: 一個魔法函數(shù),由于%matplotlib inline的存在,當輸入plt.plot()后,不必再輸入plt.show(),圖像將自動顯示出來。
  • datetime: 用來顯示時間的模塊。

數(shù)據(jù)準備

# 導入數(shù)據(jù)集
df_orginal = pd.read_csv('./taobao_persona.csv')
# 抽取部分數(shù)據(jù)
df = df_orginal.sample(frac=0.2,random_state=None)

此處使用Pandas的read_csv方法讀取數(shù)據(jù)文件,由于數(shù)據(jù)集太大,為了提高運行效率,使用sample函數(shù)隨機抽取20%的數(shù)據(jù)。

DataFrame.sample()是Pandas中的函數(shù),DataFrame是一種數(shù)據(jù)格式,代指df_orginal。frac(fraction)是抽取多少數(shù)據(jù),random_state是隨機數(shù)種子,目的是保證每次隨機抽取的數(shù)據(jù)一樣,防止執(zhí)行命令時使用不一樣的數(shù)據(jù)。

數(shù)據(jù)預處理

# 查看其中是否有缺失值,統(tǒng)計各字段缺失值
df.isnull().any().sum()
# 發(fā)現(xiàn)只有user_geohash有缺失值,且缺失的比例很高,無統(tǒng)計分析的意義,將此列刪
df.drop('user_geohash',axis=1,inplace=True)
# 將time字段拆分為日期和時段
df['date'] = df['time'].str[0:10]
df['time'] = df['time'].str[11:]
df['time'] = df['time'].astype(int)
# date用str方法取0-9位的字符,time取11位到最后一位,將time轉(zhuǎn)化成int類型。
# 將時段分為'凌晨','上午','中午','下午','晚上'
df['hour'] = pd.cut(df['time'],bins=[-1,5,10,13,18,24],labels=['凌晨','上午','中午','下午','晚上'])

結果如圖1所示。

實戰(zhàn)案例,手把手教你用 Python 構建電商用戶畫像_python

圖1 數(shù)據(jù)預處理結果

# 生成用戶標簽表,制作好的標簽都加入這個表中
users = df['user_id'].unique()
labels = pd.DataFrame(users,columns=['user_id'])
  • pd.DataFrame(): 其中數(shù)據(jù)填充的是users,列名為user_id。

結果如圖2所示。

實戰(zhàn)案例,手把手教你用 Python 構建電商用戶畫像_python_02

圖2 制作好的用戶ID

之后分析后的內(nèi)容都會放置在此表中,相當于建立了一個空白表,將自己分析后的結論一一加入。

數(shù)構建用戶行為標簽

1)對用戶瀏覽時間段進行分析

選取出各用戶瀏覽次數(shù)最多的時段,看看用戶到底在什么時間瀏覽商品比較多。

# 對用戶和時段分組,統(tǒng)計瀏覽次數(shù)
time_browse = df[df['behavior_type']==1].groupby(['user_id','hour']).item_id.count().reset_index()
time_browse.rename(columns={'item_id':'hour_counts'},inplace=True)
# 統(tǒng)計每個用戶瀏覽次數(shù)最多的時段
time_browse_max = time_browse.groupby('user_id').hour_counts.max().reset_index()
time_browse_max.rename(columns={'hour_counts':'read_counts_max'},inplace=True)
time_browse = pd.merge(time_browse,time_browse_max,how='left',on='user_id')
# 之前已經(jīng)按照user_id和hour進行了瀏覽物品次數(shù)的計數(shù)統(tǒng)計,現(xiàn)在借用瀏覽次數(shù)統(tǒng)計user_id在
# 哪個時間段瀏覽次數(shù)最多,并將其作為該用戶的瀏覽時間標簽的代表。
# 選取各用戶瀏覽次數(shù)最多的時段,如有并列最多的時段,用逗號連接
time_browse_hour=time_browse.loc[time_browse['hour_counts']==time_browse['read_counts_max'],'hour'].groupby(time_browse['user_id']).aggregate(lambda x:','.join(x)).reset_index()
time_browse_hour.head()
# 將用戶瀏覽活躍時間段加入用戶標簽表中
labels = pd.merge(labels,time_browse_hour,how='left',on='user_id')
labels.rename(columns={'hour':'time_browse'},inplace=True)
# labels相當于一張考試卷紙,上面展示的都是最后處理好的結果

結果如圖3所示。

實戰(zhàn)案例,手把手教你用 Python 構建電商用戶畫像_類目_03

圖3 用戶瀏覽時間段


  • groupby([‘key1’,‘key2’]): 多列聚合,分組鍵為列名。
  • reset_index(): 默認drop=False,可以獲得新的index,原來的index變成數(shù)據(jù)列保留下來,第一列會添加計數(shù)的數(shù)字,不會使用數(shù)據(jù)中的index。
  • rename(): 進行重命名,此處將item_id替換成hour_counts,inplace為是否原地填充。
  • pd.merge(): 將兩個表合并在一起,橫向合并,on代表通過某個主鍵,how指左合并,每行一一對應。
  • loc函數(shù): 通過行索引Index中的具體值來取指定數(shù)據(jù)。
  • aggregate函數(shù): groupby分組之后會返回多個子數(shù)據(jù)幀,該函數(shù)可以實現(xiàn)數(shù)據(jù)聚合,可以得到每個子數(shù)據(jù)幀的某些列的某些信息。
  • lambda函數(shù): 可以定義一個匿名函數(shù),lambda [arg1[, arg2, … argN]]: expression,其中參數(shù)是函數(shù)的輸入,是可選的,后面的表達式則為輸出,此處和join()函數(shù)一起用,其中每個x值能被“,”隔開;使用類似的代碼可以生成瀏覽活躍時間段,此處就不再贅述。

2)關于類目的用戶行為。

df_browse = df.loc[df['behavior_type']==1,['user_id','item_id','item_category']]
df_collect = df.loc[df['behavior_type']==2,['user_id','item_id','item_category']]
df_cart = df.loc[df['behavior_type']==3,['user_id','item_id','item_category']]
df_buy = df.loc[df['behavior_type']==4,['user_id','item_id','item_category']]

根據(jù)不同的用戶行為,如瀏覽、收藏等,分別導出數(shù)據(jù)進行分析。

# 對用戶與類目進行分組,統(tǒng)計瀏覽次數(shù)
df_cate_most_browse = df_browse.groupby(['user_id','item_category']).item_id.count().reset_index()
df_cate_most_browse.rename(columns={'item_id':'item_category_counts'},inplace=True)
# 統(tǒng)計每個用戶瀏覽次數(shù)最多的類目
df_cate_most_browse_max=df_cate_most_browse.groupby('user_id').item_category_counts.max().reset_index()
df_cate_most_browse_max.rename(columns={'item_category_counts':'item_category_counts_max'},inplace=True)
df_cate_most_browse = pd.merge(df_cate_most_browse,df_cate_most_browse_max,how='left',on='user_id')
# 將item_category的數(shù)字類型改為字符串型
df_cate_most_browse['item_category'] = df_cate_most_browse['item_category'].astype(str)
# 選取各用戶瀏覽次數(shù)最多的類目,如有并列最多的類目,用逗號連接
df_cate_browse=df_cate_most_browse.loc[df_cate_most_browse['item_category_counts']==df_cate_most_browse['item_category_counts_max'],'item_category'].groupby(df_cate_most_browse['user_id']).aggregate(lambda x:','.join(x)).reset_index()

# 將用戶瀏覽最多的類目加入用戶標簽表中
labels = pd.merge(labels,df_cate_browse,how='left',on='user_id')
labels.rename(columns={'item_category':'cate_most_browse'},inplace=True)
labels.head(5)

用戶瀏覽最多的類目如圖4所示。

實戰(zhàn)案例,手把手教你用 Python 構建電商用戶畫像_數(shù)據(jù)分析_04

圖4 瀏覽最多的類目

收藏、加購和購買最多的類目生成邏輯相同,重復操作后結果如圖5所示。

實戰(zhàn)案例,手把手教你用 Python 構建電商用戶畫像_類目_05

圖5 關于類目的用戶行為

從整理的數(shù)據(jù)中可以看出,瀏覽、加購物車、收藏、購買之前其實不一定存在明顯的必然關系,我們還需要進一步分析得到一些規(guī)律。

3)近30天用戶行為分析。

近30天購買次數(shù):

# 將購買行為按用戶進行分組,統(tǒng)計次數(shù)
df_counts_30_buy = df[df['behavior_type']==4].groupby('user_id').item_id.count().reset_index()
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ù):

# 將加購行為按用戶進行分組,統(tǒng)計次數(shù)
df_counts_30_cart = df[df['behavior_type']==3].groupby('user_id').item_id.count().reset_index()
labels = pd.merge(labels,df_counts_30_cart,how='left',on='user_id')
labels.rename(columns={'item_id':'counts_30_cart'},inplace=True)

近30天活躍天數(shù):

# 對用戶進行分組,統(tǒng)計活躍的天數(shù),包括瀏覽、收藏、加購、購買
counts_30_active = df.groupby('user_id')['date'].nunique()
labels = pd.merge(labels,counts_30_active,how='left',on='user_id')
labels.rename(columns={'date':'counts_30_active'},inplace=True)

結果如圖6所示。

實戰(zhàn)案例,手把手教你用 Python 構建電商用戶畫像_數(shù)據(jù)挖掘_06

圖6 近30天用戶行為

近30天用戶行為分析屬于中長期的用戶行為,我們可以依此判斷是否需要調(diào)整營銷策略,類似可以得到短期的7天用戶行為分析,觀察中短期或一個小周期內(nèi),用戶的行為是何種情況。

4)最后一次行為距今天數(shù)。

分析上次和本次用戶行為的時間差值可以實現(xiàn)精確推薦分析,下面我們來看看具體如何實現(xiàn)。

上次瀏覽距今天數(shù):

days_browse = df[df['behavior_type']==1].groupby('user_id')['date'].max().apply(lambda x:(datetime.strptime('2014-12-19','%Y-%m-%d')-x).days)
labels = pd.merge(labels,days_browse,how='left',on='user_id')
labels.rename(columns={'date':'days_browse'},inplace=True)

  • datetime.strptime(‘2014-12-19’,’%Y-%m-%d’)-x).days: 該部分屬于lambda中的函數(shù)表達式部分,即計算規(guī)則,此處最后取相減后的天數(shù)總和。
  • apply(): 格式為apply(func,*args,**kwargs),當一個函數(shù)的參數(shù)存在于一個元組或者一個字典中時,可間接調(diào)用這個函數(shù),并將元組或者字典中的參數(shù)按照順序傳遞給該函數(shù),返回值就是func函數(shù)的返回值。相當于循環(huán)遍歷,起到處理每一條數(shù)據(jù)的效果。

類似可以生成上次加購、購買距今天數(shù),分析得到用戶的活躍情況,如圖7所示,如果長時間沒有活躍,則需要推送一些內(nèi)容,或者發(fā)放優(yōu)惠券刺激用戶。

實戰(zhàn)案例,手把手教你用 Python 構建電商用戶畫像_數(shù)據(jù)挖掘_07

圖7 最后一次行為距今天情況統(tǒng)計

5)最近兩次購買間隔天數(shù)。

df_interval_buy = df[df['behavior_type']==4].groupby(['user_id','date']).item_id.count().reset_index()
interval_buy = df_interval_buy.groupby('user_id')['date'].apply(lambda x:x.sort_values().diff(1).dropna().head(1)).reset_index()
interval_buy['date'] = interval_buy['date'].apply(lambda x : x.days)
interval_buy.drop('level_1',axis=1,inplace=True)
interval_buy.rename(columns={'date':'interval_buy'},inplace=True)
labels = pd.merge(labels,interval_buy,how='left',on='user_id')

用購買間隔數(shù)分析用戶的購買頻率,方便確定用戶的消費活躍等級,精準制定營銷方式。結果如圖8所示。

實戰(zhàn)案例,手把手教你用 Python 構建電商用戶畫像_類目_08

圖8 最近兩次購買間隔天數(shù)統(tǒng)計

6)是否瀏覽未下單。

df_browse_buy=df.loc[(df['behavior_type']==1)|(df['behavior_type']==4),['user_id','item_id','behavior_type','time']]
browse_not_buy=pd.pivot_table(df_browse_buy,index=['user_id','item_id'],
columns=['behavior_type'],values=['time'],aggfunc=['count'])
browse_not_buy.columns = ['browse','buy']
browse_not_buy.fillna(0,inplace=True)
# 添加了一列browse_not_buy,初始值為0。
browse_not_buy['browse_not_buy'] = 0
# 瀏覽數(shù)>0,購買數(shù)=0的數(shù)據(jù)輸出1.
browse_not_buy.loc[(browse_not_buy['browse']>0) & (browse_not_buy['buy']==0),'browse_not_buy'] = 1
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')
labels['browse_not_buy'] = labels['browse_not_buy'].apply(lambda x: '是' if x>0 else '否')

  • |: 在Python語句中表示或,&表示且。
  • pd.pivot_table(): 透視表功能,df_browse_buy為data塊,values可以對需要的計算數(shù)據(jù)進行篩選,aggfunc參數(shù)可以設置我們對數(shù)據(jù)聚合時進行的函數(shù)操作。
  • fillna: 會填充NaN數(shù)據(jù),返回填充后的結果,inplace=True代表原地填充。

結果如圖9所示。

實戰(zhàn)案例,手把手教你用 Python 構建電商用戶畫像_數(shù)據(jù)挖掘_09

圖9 是否瀏覽未下單情況統(tǒng)計

針對瀏覽未下單的用戶要加大推廣力度,可以增加優(yōu)惠券的發(fā)放次數(shù),促進購物。

7)是否加購未下單。

df_cart_buy=df.loc[(df['behavior_type']==3)|(df['behavior_type']==4),['user_id','item_id','behavior_type','time']]
cart_not_buy=pd.pivot_table(df_cart_buy,index=['user_id','item_id'],columns=['behavior_type'],values=['time'],aggfunc=['count'])
cart_not_buy.columns = ['cart','buy']
cart_not_buy.fillna(0,inplace=True)
cart_not_buy['cart_not_buy'] = 0
cart_not_buy.loc[(cart_not_buy['cart']>0) & (cart_not_buy['buy']==0),'cart_not_buy'] = 1
cart_not_buy = cart_not_buy.groupby('user_id')['cart_not_buy'].sum().reset_index()
labels = pd.merge(labels,cart_not_buy,how='left',on='user_id')
labels['cart_not_buy'] = labels['cart_not_buy'].apply(lambda x: '是' if x>0 else '否')

結果如圖10所示。

實戰(zhàn)案例,手把手教你用 Python 構建電商用戶畫像_數(shù)據(jù)挖掘_10

圖10 是否加購未下單情況統(tǒng)計

制定營銷策略時,要重點注意這部分人群,因為加購未下單的購買轉(zhuǎn)化率是最大的,有成功下單、最大潛力的客戶就在這里。

構建用戶屬性標簽

1)是否復購用戶:

buy_again = df[df['behavior_type']==4].groupby('user_id')['item_id'].count().reset_index()
buy_again.rename(columns={'item_id':'buy_again'},inplace=True)
labels = pd.merge(labels,buy_again,how='left',on='user_id')
labels['buy_again'].fillna(-1,inplace=True)
# 未購買的用戶標記為'未購買',有購買未復購的用戶標記為'否',有復購的用戶標記為'是'
labels['buy_again'] = labels['buy_again'].apply(lambda x: '是' if x>1 else '否' if x==1 else '未購買')

結果如圖11所示。

實戰(zhàn)案例,手把手教你用 Python 構建電商用戶畫像_數(shù)據(jù)挖掘_11

圖11 是否復購用戶統(tǒng)計

2)訪問活躍度:

user_active_level = labels['counts_30_active'].value_counts().sort_index(ascending=False)
plt.figure(figsize=(16,9))
user_active_level.plot(title='30天內(nèi)訪問次數(shù)與訪問人數(shù)的關系',fontsize=18)
plt.ylabel('訪問人數(shù)',fontsize=14)
plt.xlabel('訪問次數(shù)',fontsize=14)
# 用于顯示中文
plt.rcParams["font.sans-serif"] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
# 先將user_active_level全部設置成高,再搜索數(shù)值<16的部分,設置成低
labels['user_active_level'] = '高'
labels.loc[labels['counts_30_active']<=16,'user_active_level'] = '低'

結果如圖12所示。

實戰(zhàn)案例,手把手教你用 Python 構建電商用戶畫像_python_12

圖12 30天內(nèi)訪問次數(shù)與訪問人數(shù)的關系


  • value_counts(): 查看表格某列中有多少個不同值,并計算每個不同值在該列中有多少重復值。
  • sort_index(): 按照某一列的大小進行排序,ascending=False是按照從大到小排序。
  • plt.figure(figsize=(a,b)): 創(chuàng)建畫板,figsize代表寬為a,高為b的圖形,單位為英寸。
  • plt.ylabel: 設置y軸,fontsize是字體大小。
  • plt.xlabel: 設置x軸。

通過圖12可以看出,訪問次數(shù)多的用戶比訪問次數(shù)少的用戶數(shù)量多,且以15次左右為拐點,因此定義訪問次數(shù)小于等于16次的用戶為低活躍用戶,訪問次數(shù)大于16次的用戶定義為高活躍用戶,此定義只是從用戶的角度出發(fā),工作中當從業(yè)務角度定義。訪問次數(shù)多的訪客比訪問次數(shù)少的訪客數(shù)量多,與絕大多數(shù)的產(chǎn)品訪問規(guī)律相反,從側面反映了用戶黏性之強。

3)購買活躍度:

buy_active_level = labels['counts_30_buy'].value_counts().sort_index(ascending= False)
plt.figure(figsize=(16,9))
buy_active_level.plot(title='30天內(nèi)購買次數(shù)與購買人數(shù)的關系',fontsize=18)
plt.ylabel('購買人數(shù)',fontsize=14)
plt.xlabel('購買次數(shù)',fontsize=14)
labels['buy_active_level'] = '高'
labels.loc[labels['counts_30_buy']<=14,'buy_active_level'] = '低'

結果如圖13所示。

實戰(zhàn)案例,手把手教你用 Python 構建電商用戶畫像_類目_13

圖13 30天內(nèi)購買次數(shù)與購買人數(shù)的關系

由圖13可知,14次左右是個拐點,因此定義購買次數(shù)小于等于14次的用戶為低活躍用戶,大于14次的用戶為高活躍用戶。

4)購買的品類是否單一:

buy_single=df[df['behavior_type']==4].groupby('user_id').item_category.nunique().reset_index()
buy_single.rename(columns={'item_category':'buy_single'},inplace=True)

labels = pd.merge(labels,buy_single,how='left',on='user_id')

labels['buy_single'].fillna(-1,inplace=True)

labels['buy_single'] = labels['buy_single'].apply(lambda x: '是' if x>1 else '否' if x==1 else '未購買' )

結果如圖14所示。

實戰(zhàn)案例,手把手教你用 Python 構建電商用戶畫像_類目_14

圖14 購買品類單一情況統(tǒng)計

了解用戶購買的品類有利于構建用戶群體行為,比如該群體統(tǒng)一對化妝品消費占比巨大,則該用戶群體的主要特征標簽之一就是化妝品。

5)用戶價值分組(RFM模型):

last_buy_days = labels['days_buy'].value_counts().sort_index()
plt.figure(figsize=(16,9))
last_buy_days.plot(title='最后一次購買距今天數(shù)與購買人數(shù)的關系',fontsize=18)
plt.ylabel('購買人數(shù)',fontsize=14)
plt.xlabel('距今天數(shù)',fontsize=14)

結果如圖15所示。

實戰(zhàn)案例,手把手教你用 Python 構建電商用戶畫像_數(shù)據(jù)挖掘_15

圖15 最后購買行為距今天數(shù)與購買人數(shù)的關系

使用RFM模型分析:

labels['buy_days_level'] = '高'
labels.loc[labels['days_buy']>8,'buy_days_level'] = '低'
labels['rfm_value'] = labels['buy_active_level'].str.cat(labels['buy_days_level'])
def trans_value(x):
if x == '高高':
return '重要價值客戶'
elif x == '低高':
return '重要深耕客戶'
elif x == '高低':
return '重要喚回客戶'
else:
return '即將流失客戶'
labels['rfm'] = labels['rfm_value'].apply(trans_value)
# 此處的apply()調(diào)用了一個自己定義(def)的函數(shù)
labels.drop(['buy_days_level','rfm_value'],axis=1,inplace=True)
labels['rfm'].value_counts()

結果如圖16所示。

實戰(zhàn)案例,手把手教你用 Python 構建電商用戶畫像_數(shù)據(jù)挖掘_16

圖16 RFM模型分析結果


  • str.cat() 是指將兩個獨立的字符串拼接,此處將
  • ’buy_active_level‘和’buy_days_level’ 拼接。如果要在兩個合并的列中間加一個分隔符號,可在cat括號內(nèi)加:sep=’-’,用-連接合并內(nèi)容。

將buy_active_level和buy_days_level組合,形成“高高”或者“高低”等。將兩個重要指標合并后,每個user_id進入不同的分類組。RFM模型是衡量客戶價值和客戶創(chuàng)利能力的重要工具和手段,其中,R(recently):最近一次消費;F(Frequently):消費頻率;M(Monetary):消費金額。

對最后輸出的用戶群體制定不同的營銷策略。針對重要價值客戶要予以關注并維護;針對重要深耕用戶,予以相應的價格刺激,如折扣和捆綁銷售等增加用戶的購買頻率,提高黏性;針對重要喚回用戶,要在特定時間點進行刺激,比如進行產(chǎn)品賣點刺激、品牌灌輸?shù)?,不斷加強他們對品牌的認可,提高忠誠度;針對流失客戶,在此例中,因其數(shù)量占三分之一左右,需進一步分析得出流失原因。

技術交流

歡迎轉(zhuǎn)載、收藏、有所收獲點贊支持一下!

實戰(zhàn)案例,手把手教你用 Python 構建電商用戶畫像_類目_17

目前開通了技術交流群,群友已超過2000人,添加時最好的備注方式為:來源+興趣方向,方便找到志同道合的朋友


方式③、微信搜索公眾號:Python學習與數(shù)據(jù)挖掘,后臺回復:加群


實戰(zhàn)案例,手把手教你用 Python 構建電商用戶畫像_python_18



本文摘自 :https://blog.51cto.com/u

開通會員,享受整站包年服務立即開通 >