排行榜 统计
  • 建站日期:2015-05-20
  • 文章总数:234 篇
  • 评论总数:892 条
  • 分类总数:6 个
  • 最后更新:5月8日

项目实践:电商用户画像标签(上)

本文阅读 8 分钟
首页 数据 正文

用户标签.jpg

本实践项目基于一个月的淘宝用户行为,给用户打标签 此项目为上部,包含用户属性标签和用户行为标签。 文末可下载文中所需的数据集。

标签总览

由于数据集的局限,此项目的画像标签只是庞大用户画像的一部分,基于已有的数据集进行制作
81531-hasviefl5bo.png15096-2noldhlg91t.png

导入所需库

#导入库
%matplotlib inline
import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
import gc
import warnings
warnings.filterwarnings('ignore')
from datetime import datetime

导入数据集

#导入数据集
df_orginal = pd.read_csv('/home/kesci/input/mydata9388/taobao_persona.csv')

数据预处理

数据抽样

数据集太大,为了提高运行效率,只随机抽取20%的数据

#数据集太大,为了提高运行效率,只随机抽取20%的数据
df = df_orginal.sample(frac=0.2,random_state=None)

#回收内存
del df_orginal
gc.collect()

输出结果:21

缺失值处理

df.info()

输出:
<class 'pandas.core.frame.DataFrame'>
Int64Index: 4658205 entries, 13077081 to 21758719
Data columns (total 6 columns):
user_id int64
item_id int64
behavior_type int64
user_geohash object
item_category int64
time object
dtypes: int64(4), object(2)
memory usage: 248.8+ MB

df.shape

输出:(4658205, 6)

#查看各字段的缺失值数量
df.isnull().sum()

输出:

user_id 0
item_id 0
behavior_type 0
user_geohash 3183516
item_category 0
time 0
dtype: int64

只有user_geohash有缺失值,且缺失的比例很高,无统计分析的意义,将此列删除

输入:

df.drop('user_geohash',axis=1,inplace=True)

日期与时段处理

输入:

#将time字段拆分为日期和时段
df['date'] = df['time'].str[0:10]
df['date'] = pd.to_datetime(df['date'],format='%Y-%m-%d')
df['time'] = df['time'].str[11:]
df['time'] = df['time'].astype(int)

输入:

#将时段分为'凌晨'、'上午'、'中午'、'下午'、'晚上'
df['hour'] = pd.cut(df['time'],bins=[-1,5,10,13,18,24],labels=['凌晨','上午','中午','下午','晚上'])

制作用户标签

输入:

#生成用户标签表,制作好的标签都加入这个表中
users = df['user_id'].unique()
labels = pd.DataFrame(users,columns=['user_id'])

用户行为标签

用户浏览活跃时间段

输入:

#对用户和时段分组,统计浏览次数
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)

输入:

#统计每个用户浏览次数最多的时段
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')

输入:

#选取各用户浏览次数最多的时段,如有并列最多的时段,用逗号连接
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()

输出:

07728-dki6xks3xxk.png66583-2chavij39h3.png

#将用户浏览活跃时间段加入到用户标签表中
labels = pd.merge(labels,time_browse_hour,how='left',on='user_id')
labels.rename(columns={'hour':'time_browse'},inplace=True)

用户购买活跃时间段

输入:

#生成逻辑与浏览活跃时间段相同
time_buy = df[df['behavior_type']==4].groupby(['user_id','hour']).item_id.count().reset_index()
time_buy.rename(columns={'item_id':'hour_counts'},inplace=True)
time_buy_max = time_buy.groupby('user_id').hour_counts.max().reset_index()
time_buy_max.rename(columns={'hour_counts':'buy_counts_max'},inplace=True)
time_buy = pd.merge(time_buy,time_buy_max,how='left',on='user_id')
time_buy_hour = time_buy.loc[time_buy['hour_counts']==time_buy['buy_counts_max'],'hour'].groupby(time_buy['user_id']).aggregate(lambda x:','.join(x)).reset_index()

输入:

time_buy_hour.head()

输出:
61284-pe5l75attzb.png51949-e5ophm0g7i.png

输入:

#将用户购买活跃时间段加入到用户标签表中
labels = pd.merge(labels,time_buy_hour,how='left',on='user_id')
labels.rename(columns={'hour':'time_buy'},inplace=True)

输入:

del time_browse
del time_buy
del time_browse_hour
del time_browse_max
del time_buy_hour
del time_buy_max
gc.collect()

输出:168

关于类目的用户行为

输入:

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']]

浏览最多的类目

输入:

#对用户与类目进行分组,统计浏览次数
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)

输入:

#统计每个用户浏览次数最多的类目
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')

输入:

df_cate_most_browse['item_category'] = df_cate_most_browse['item_category'].astype(str)

输入:

#选取各用户浏览次数最多的类目,如有并列最多的类目,用逗号连接
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()

输入:

df_cate_browse.head()

输出:
40612-kggha7p7b8.png49922-1eb4pvwdzfh.png

输入:

#将用户浏览最多的类目加入到用户标签表中
labels = pd.merge(labels,df_cate_browse,how='left',on='user_id')
labels.rename(columns={'item_category':'cate_most_browse'},inplace=True)

收藏最多的类目

输入:

#生成逻辑与浏览最多的类目相同
df_cate_most_collect = df_collect.groupby(['user_id','item_category']).item_id.count().reset_index()
df_cate_most_collect.rename(columns={'item_id':'item_category_counts'},inplace=True)
df_cate_most_collect_max = df_cate_most_collect.groupby('user_id').item_category_counts.max().reset_index()
df_cate_most_collect_max.rename(columns={'item_category_counts':'item_category_counts_max'},inplace=True)
df_cate_most_collect = pd.merge(df_cate_most_collect,df_cate_most_collect_max,how='left',on='user_id')
df_cate_most_collect['item_category'] = df_cate_most_collect['item_category'].astype(str)
df_cate_collect = df_cate_most_collect.loc[df_cate_most_collect['item_category_counts']==df_cate_most_collect['item_category_counts_max'],'item_category'].groupby(df_cate_most_collect['user_id']).aggregate(lambda x:','.join(x)).reset_index()

输入:

df_cate_collect.head()

输出:

92886-xyd911c83si.png29538-8uqote7spud.png

输入:

labels = pd.merge(labels,df_cate_collect,how='left',on='user_id')
labels.rename(columns={'item_category':'cate_most_collect'},inplace=True)

加购最多的类目

输入:

#生成逻辑与浏览最多的类目相同
df_cate_most_cart = df_cart.groupby(['user_id','item_category']).item_id.count().reset_index()
df_cate_most_cart = df_cart.groupby(['user_id','item_category']).item_id.count().reset_index()
df_cate_most_cart.rename(columns={'item_id':'item_category_counts'},inplace=True)
df_cate_most_cart_max = df_cate_most_cart.groupby('user_id').item_category_counts.max().reset_index()
df_cate_most_cart_max.rename(columns={'item_category_counts':'item_category_counts_max'},inplace=True)
df_cate_most_cart = pd.merge(df_cate_most_cart,df_cate_most_cart_max,how='left',on='user_id')
df_cate_most_cart['item_category'] = df_cate_most_cart['item_category'].astype(str)
df_cate_cart = df_cate_most_cart.loc[df_cate_most_cart['item_category_counts']==df_cate_most_cart['item_category_counts_max'],'item_category'].groupby(df_cate_most_cart['user_id']).aggregate(lambda x:','.join(x)).reset_index()

输入:

df_cate_cart.head()

输出:
84879-ymvqfi00jy.png52915-uu3lliuxarh.png

输入:

labels = pd.merge(labels,df_cate_cart,how='left',on='user_id')
labels.rename(columns={'item_category':'cate_most_cart'},inplace=True)

购买最多的类目

输入:

#生成逻辑与浏览最多的类目相同
df_cate_most_buy = df_buy.groupby(['user_id','item_category']).item_id.count().reset_index()
df_cate_most_buy = df_buy.groupby(['user_id','item_category']).item_id.count().reset_index()
df_cate_most_buy.rename(columns={'item_id':'item_category_counts'},inplace=True)
df_cate_most_buy_max = df_cate_most_buy.groupby('user_id').item_category_counts.max().reset_index()
df_cate_most_buy_max.rename(columns={'item_category_counts':'item_category_counts_max'},inplace=True)
df_cate_most_buy = pd.merge(df_cate_most_buy,df_cate_most_buy_max,how='left',on='user_id')
df_cate_most_buy['item_category'] = df_cate_most_buy['item_category'].astype(str)
df_cate_buy = df_cate_most_buy.loc[df_cate_most_buy['item_category_counts']==df_cate_most_buy['item_category_counts_max'],'item_category'].groupby(df_cate_most_buy['user_id']).aggregate(lambda x:','.join(x)).reset_index()

输入:

df_cate_buy.head()

输出:

39001-i2370vlq8dn.png56926-9835xqg0p7d.png

输入:

labels = pd.merge(labels,df_cate_buy,how='left',on='user_id')
labels.rename(columns={'item_category':'cate_most_buy'},inplace=True)

输入:

del df_browse
del df_collect
del df_cart
del df_buy
del df_cate_most_browse
del df_cate_most_collect
del df_cate_most_buy
del df_cate_most_cart
del df_cate_most_browse_max
del df_cate_most_collect_max
del df_cate_most_cart_max
del df_cate_most_buy_max
del df_cate_browse
del df_cate_collect
del df_cate_cart
del df_cate_buy
gc.collect(0)

输出:112

30天用户行为

数据集中的数据正好是一个月,30天的数据即整个数据集的数据

近30天购买次数

输入:

#将购买行为按用户进行分组,统计次数
df_counts_30_buy = df[df['behavior_type']==4].groupby('user_id').item_id.count().reset_index()

输入:

df_counts_30_buy.head()

输出:

98485-u927i9w3la.png84337-6pv4z7750r3.png

输入:

labels = pd.merge(labels,df_counts_30_buy,how='left',on='user_id')
labels.rename(columns={'item_id':'counts_30_buy'},inplace=True)

近30天加购次数

输入:

#将加购行为按用户进行分组,统计次数
df_counts_30_cart = df[df['behavior_type']==3].groupby('user_id').item_id.count().reset_index()

输入:

df_counts_30_cart.head()

输出:

01067-7z2hmrf0qp7.png52751-h27zdphct0b.png

输入:

labels = pd.merge(labels,df_counts_30_cart,how='left',on='user_id')
labels.rename(columns={'item_id':'counts_30_cart'},inplace=True)

近30天活跃天数

输入:

#对用户进行分组,统计活跃的天数,包括浏览、收藏、加购、购买
counts_30_active = df.groupby('user_id')['date'].nunique()

输入:

counts_30_active.head()

输出:

user_id
492 11
3726 15
19137 6
36465 7
37101 19
Name: date, dtype: int64

输入:

labels = pd.merge(labels,counts_30_active,how='left',on='user_id')
labels.rename(columns={'date':'counts_30_active'},inplace=True)

输入:

del df_counts_30_buy
del df_counts_30_cart
del counts_30_active
gc.collect()

输出:238

7天用户行为

输入:

#数据集中的最后日期是12月18号,统计11号之后的用户行为
df_near_7 = df[df['date']>datetime.strptime('2014-12-11', '%Y-%m-%d')]

近7天购买次数

输入:

df_counts_7_buy = df_near_7[df_near_7['behavior_type']==4].groupby('user_id').item_id.count().reset_index()

输入:

df_counts_7_buy.head()

输出:

22508-6dl0clpu59s.png47544-2mkphxndgci.png

输入:

labels = pd.merge(labels,df_counts_7_buy,how='left',on='user_id')
labels.rename(columns={'item_id':'counts_7_buy'},inplace=True)

近7天加购次数

输入:

df_counts_7_cart = df_near_7[df_near_7['behavior_type']==3].groupby('user_id').item_id.count().reset_index()

输入:

df_counts_7_cart.head()

输出:

50423-sm4p30asp8.png55333-ppcseloafv.png

输入:

labels = pd.merge(labels,df_counts_7_cart,how='left',on='user_id')
labels.rename(columns={'item_id':'counts_7_cart'},inplace=True)

近7天活跃天数

输入:

counts_7_active = df_near_7.groupby('user_id')['date'].nunique()

输入:

counts_7_active.head()

输出:

user_id
492 4
3726 5
19137 1
36465 2
37101 5
Name: date, dtype: int64

输入:

labels = pd.merge(labels,counts_7_active,how='left',on='user_id')
labels.rename(columns={'date':'counts_7_active'},inplace=True)

输入:

del df_counts_7_buy
del df_counts_7_cart
del counts_7_active
gc.collect()

输出:112

最后一次行为距今天数

上次浏览距今天数

输入:

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)

输入:

days_browse.head()

输出:

user_id
492 1
3726 1
19137 7
36465 3
37101 3
Name: date, dtype: int64

输入:

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

输入:

labels.rename(columns={'date':'days_browse'},inplace=True)

上次加购距今天数

输入:

days_cart = df[df['behavior_type']==3].groupby('user_id')['date'].max().apply(lambda x:(datetime.strptime('2014-12-19','%Y-%m-%d')-x).days)

输入:

days_cart.head()

输出:

user_id
3726 1
37101 8
45561 1
59436 4
61797 18
Name: date, dtype: int64

输入:

labels = pd.merge(labels,days_cart,how='left',on='user_id')
labels.rename(columns={'date':'days_cart'},inplace=True)

上次购买距今天数

输入:

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)

输入:

days_buy.head()

输出:

user_id
38745 23
45561 6
53394 22
59436 7
100605 7
Name: date, dtype: int64

输入:

labels = pd.merge(labels,days_buy,how='left',on='user_id')
labels.rename(columns={'date':'days_buy'},inplace=True)

输入:

del days_browse
del days_buy
del days_cart
gc.collect()

输出:42

最近两次购买间隔天数

输入:

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)

输入:

interval_buy.head()

输出:

94054-ganrrezl64q.png03410-ypvjhna28k.png

输入:

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

输入:

del df_interval_buy
gc.collect()

输出:70

是否浏览未下单

输入:

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['browse_not_buy'] = 0

输入:

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()

输入:

browse_not_buy.head()

输出:

03494-pgcpcktrz5a.png20581-zhq3dux0aek.png

输入:

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 '否')

是否加购未下单

输入:

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()

输入:

cart_not_buy.head()

输出:

76383-97iperginj8.png00860-1322qubfeqpc.png

输入:

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 '否')

用户属性标签

是否复购用户

输入:

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)

输入:

buy_again.head()

输出:

56379-fu7hby884r5.png44030-pkibocaoig9.png

输入:

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 '未购买')

访问活跃度

输入:

user_active_level = labels['counts_30_active'].value_counts().sort_index(ascending=False)

输入:

plt.figure(figsize=(16,9))
user_active_level.plot(title='30天内访问次数与访问人数的关系',fontsize=18)
plt.ylabel('访问人数',fontsize=14)
plt.xlabel('访问次数',fontsize=14)

输出:

Text(0.5, 0, '访问次数')

40738-yw8nk5jzuob.png75791-ugmxrgm4gxf.png
(30天内访问次数与访问人数的关系)

总体上看,访问次数多的访客比访问次数少的访客数量多,且以15次左右为拐点,因此定义访问次数小于等于16次的为低活跃,访问次数大于16次的定义为高活跃
此定义只是从用户的分布角度出发,工作中当从业务出发定义是否活跃
PS:访问次数多的访客比访问次数少的访客数量多,与绝大多数的产品访问规律相反,从侧面反映了淘宝的用户黏性之强

输入:

labels['user_active_level'] = '高'
labels.loc[labels['counts_30_active']<=16,'user_active_level'] = '低'

购买活跃度

输入:

buy_active_level = labels['counts_30_buy'].value_counts().sort_index(ascending=False)

输入:

plt.figure(figsize=(16,9))
buy_active_level.plot(title='30天内购买次数与购买人数的关系',fontsize=18)
plt.ylabel('购买人数',fontsize=14)
plt.xlabel('购买次数',fontsize=14)

输出:

Text(0.5, 0, '购买次数')

07257-zd6uxih3n7f.png99364-1oudcdu0b4.png
(30天内购买次数与购买人数的关系)

14次左右是个拐点,因此定义购买次数小于等于14次为低活跃,大于14次为高活跃
此定义只是从用户的分布角度出发,工作中当从业务出发定义是否活跃

输入:

labels['buy_active_level'] = '高'
labels.loc[labels['counts_30_buy']<=14,'buy_active_level'] = '低'

购买的品类是否单一

输入:

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 '未购买' )

用户价值分组(RFM)

last_buy_days = labels['days_buy'].value_counts().sort_index()

输入:

plt.figure(figsize=(16,9))
last_buy_days.plot(title='最后一次购买距今天数与购买人数的关系',fontsize=18)
plt.ylabel('购买人数',fontsize=14)
plt.xlabel('距今天数',fontsize=14)

输出:

Text(0.5, 0, '距今天数')

80181-dfgy6k6ixsb.png77467-3bd7skbv7ly.png
(最后一次购买距今天数与购买人数的关系)

注:访问异常的那天为双12

输入:

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)

输入:

labels.drop(['buy_days_level','rfm_value'],axis=1,inplace=True)

输入:

labels['rfm'].value_counts()

输出:

重要深耕客户 7167
重要价值客户 7142
即将流失客户 5631
重要唤回客户 16
Name: rfm, dtype: int64

输入:

labels.head()

输出:

59120-wfve5463dc.png12092-jquvrsccdwc.png

数据集下载

做产品经理此处内容已经被作者隐藏,请输入验证码查看内容
验证码:
请关注本站微信公众号,回复“暗号”,获取验证码。在微信里搜索“做产品经理”或者“zuopmcom”或者微信扫描右侧二维码都可以关注本站微信公众号。

相关文章

项目实践:电商用户画像标签(上)

![用户标签.jpg][1] 本实践项目基于一个月的淘宝用户行为,给用户打标签 此项目为上部,包含用户属性标签和用户行为标签。 文末可下载文中所需的数据集。....


项目实践:电商用户画像标签(下)

![用户标签.jpg][1] 上篇主要介绍电商用户画像打标签的实践,本文主要对标签加入权重处理。包括用户个性化标签、用户偏好标签、群体偏好标签,涉及到TF-I....

本文经授权后发布,本文观点不代表立场
-- 展开阅读全文 --
我不是产品经理:移动互联网商业模式下的用户增长epub高清电子书
« 上一篇 04-23
项目实践:电商用户画像标签(下)
下一篇 » 04-26

发表评论

成为第一个评论的人

作者信息

广告

热门文章

标签TAG

热评文章