项目三、电商用户画像分析(上)

一、前言:

电商用户画像分析:用户画像是通过分析用户的基础信息、特征偏好、社会属性等各维度的数据,刻画出用户的信息全貌,它是建立在一系列属性数据之上的目标用户模型。用户画像的本质是一个用以描述用户需求的工具。用户画像一般是产品设计、运营人员从用户群体中抽象出来的典型用户,从中可以挖掘用户价值,提供个性化推荐、精准营销等服务。
电商用户画像分析的作用:

二、理解数据与分析思路

1.导入使用的包:

#加上后可以直接在界面画图.
%matplotlib inline  

#导入包
import pandas as pd
import numpy as np
import matplotlib
import matplotlib.pyplot as plt

# 减少绘图产生的问题
matplotlib.rcParams['font.sans-serif'] = ['SimHei']  # 指定字体
matplotlib.rcParams['font.family']='sans-serif'  
matplotlib.rcParams['axes.unicode_minus'] = False #解决负号'-'显示为方块的问题  

# 导入数据库包,从数据库里读取数据与存储数据
import pymysql
pymysql.install_as_MySQLdb()
from sqlalchemy import create_engine

import gc #gc模块可以回收内存
import warnings
warnings.filterwarnings('ignore')#减少报错
from datetime import datetime

2.导入数据:

#导入数据集
df = pd.read_excel('order_data.xlsx')
df_user = pd.read_excel('user_data.xlsx')

3.理解数据:

df.head()

order_data共有五个字段,分别为,其中behavior_type中1为浏览,2为收藏,3为加购,4为购买

df_user.head()


4.分析维度:

三、数据预处理:

1.缺失值处理:



2.时间格式转换:

3.制作用户标签表:

四、分析过程:

1、用户活跃的时间
1.1 用浏览活跃时间段

time_brows = df[df['behavior_type']==1].groupby(['user_id','hour']).agg({'item_id':'count'}).reset_index()
time_brows.rename(columns={'item_id':'hour_counts'},inplace=True)
#求出每个用户最活跃的时间段
time_brows_max = time_brows.groupby('user_id').hour_counts.max().reset_index()
time_brows_max.rename(columns = {'hour_counts':'hour_counts_max'},inplace = True)
time_brows = pd.merge(time_brows,time_brows_max,how ='left',on = 'user_id')
#选取各用户浏览次数最多的时段,如有并列最多的时段,用逗号连接
time_brows_hour = time_brows.loc[time_brows['hour_counts']==time_brows['hour_counts_max'],'hour'].groupby(time_brows['user_id']).aggregate(lambda x:','.join(x)).reset_index()
#将用户浏览活跃时间段加入到用户标签表中
labels = pd.merge(labels,time_brows_hour,how = 'left',on = 'user_id')
labels.rename(columns = {'hour':'time_browse'},inplace = True)
#查看标签表
labels.head()

1.2 用户购买活跃时间段

time_buy = df[df['behavior_type'] == 4].groupby(['user_id','hour']).item_id.count().reset_index()
time_buy.rename(columns = {'item_id':'time_buy_count'},inplace = True)
time_buy_max = time_buy.groupby('user_id').time_buy_count.max().reset_index()
time_buy_max.rename(columns = {'time_buy_count':'time_buy_count_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['time_buy_count'] == time_buy['time_buy_count_max'],'hour'].groupby(time_buy['user_id']).aggregate(lambda x:','.join(x)).reset_index()
labels = pd.merge(labels,time_buy_hour,how = 'left',on = 'user_id')
labels.rename(columns = {'hour':'buy_hour'},inplace = True)
#查看标签表
labels.head()

1.3 清除缓存:

del time_brows
del time_brows_max
del time_buy
del time_buy_max
del time_buy_hour
del time_brows_hour
gc.collect()

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

2.1 浏览最多的类目

#对用户和类目进行分组,统计浏览次数
df_browse_count = df_browse.groupby(['user_id','item_category']).item_id.count().reset_index()
df_browse_count.rename(columns = {'item_id':'item_category_counts'},inplace = True)

#按照用户进行分组,统计出每个用户浏览最多的类目
df_browse_count_max = df_browse_count.groupby('user_id').item_category_counts.max().reset_index()
df_browse_count_max.rename(columns = {'item_category_counts':'item_category_counts_max'},inplace = True)
df_browse_count = pd.merge(df_browse_count,df_browse_count_max,how = 'left',on = 'user_id')

#将类目转换成字符串格式,否则会报错
df_browse_count['item_category'] = df_browse_count['item_category'].astype(str)

#选取各用户浏览次数最多的类目,如有并列最多的类目,用逗号连接
df_browse_count= df_browse_count.loc[df_browse_count['item_category_counts']==df_browse_count['item_category_counts_max'],'item_category'].groupby(df_browse_count['user_id']).aggregate(lambda x:','.join(x)).reset_index()

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

2.2 收藏最多的类目

#按照用户、类目进行分组,统计收藏次数
df_collect_count = df_collect.groupby(['user_id','item_category']).item_id.count().reset_index()
df_collect_count.rename(columns = {'item_id':'item_category_count'},inplace = True)
#按照用户分组,统计用户收藏最多的类目和
df_collect_count_max = df_collect_count.groupby('user_id').item_category_count.max().reset_index()
df_collect_count_max.rename(columns = {'item_category_count':'item_category_count_max'},inplace = True)
df_collect_count = pd.merge(df_collect_count,df_collect_count_max,how = 'left',on ='user_id')
#将类目转换成字符串格式,否则会报错
df_collect_count['item_category'] = df_collect_count['item_category'].astype(str)
#选取各用户收藏次数最多的类目,如有并列最多的类目,用逗号连接
df_collect = df_collect_count.loc[df_collect_count['item_category_count']==df_collect_count['item_category_count_max'],'item_category'].groupby(df_collect_count['user_id']).aggregate(lambda x:','.join(x)).reset_index()
df_collect.rename(columns = {'item_category':'cate_most_collect'},inplace = True)
#将用户收藏最多的类目加到标签表
labels = pd.merge(labels,df_collect,how ='left',on = 'user_id')
labels.head()

2.3 加购最多的类目

df_cart_count = df_cart.groupby(['user_id','item_category']).item_id.count().reset_index()
df_cart_count.rename(columns = {'item_id':'item_category_count'},inplace = True)
df_cart_count_max = df_cart_count.groupby('user_id').item_category_count.max().reset_index()
df_cart_count_max.rename(columns = {'item_category_count':'item_category_count_max'},inplace = True)
df_cart_count = pd.merge(df_cart_count,df_cart_count_max,how = 'left',on ='user_id')
df_cart_count['item_category'] = df_cart_count['item_category'].astype(str)
df_cart = df_cart_count.loc[df_cart_count['item_category_count']==df_cart_count['item_category_count_max'],'item_category'].groupby(df_cart_count['user_id']).aggregate(lambda x:','.join(x)).reset_index()
df_cart.rename(columns = {'item_category':'cate_most_cart'},inplace = True)
labels = pd.merge(labels,df_cart,how ='left',on = 'user_id')
labels.head()

2.4 购买最多的类目

df_buy_count = df_buy.groupby(['user_id','item_category']).item_id.count().reset_index()
df_buy_count.rename(columns = {'item_id':'item_category_count'},inplace = True)
df_buy_count_max = df_buy_count.groupby('user_id').item_category_count.max().reset_index()
df_buy_count_max.rename(columns = {'item_category_count':'item_category_count_max'},inplace = True)
df_buy_count = pd.merge(df_buy_count,df_buy_count_max,how ='left',on ='user_id')
df_buy_count['item_category'] = df_buy_count['item_category'].astype(str)
df_buy = df_buy_count.loc[df_buy_count['item_category_count']==df_buy_count['item_category_count_max'],'item_category'].groupby(df_buy_count['user_id']).aggregate(lambda x:','.join(x)).reset_index()
df_buy.rename(columns = {'item_category':'cate_most_buy'},inplace = True)
labels = pd.merge(labels,df_buy,how = 'left',on = 'user_id')
labels.head()


3、30天用户行为
3.1 近30天购买次数

#将购买行为按用户进行分组,统计次数
df_count_30_buy = df[df['behavior_type'] == 4].groupby('user_id').item_id.count().reset_index()
labels = pd.merge(labels,df_count_30_buy,how = 'left',on = 'user_id')
labels.rename(columns = {'item_id':'count_30_buy'},inplace = True)
labels.head()

3.2 近30天加购次数

#将加购行为按用户进行分组,统计次数
df_count_30_cart = df[df['behavior_type'] == 3].groupby('user_id').item_id.count().reset_index()
labels = pd.merge(labels,df_count_30_cart,how = 'left',on = 'user_id')
labels.rename(columns = {'item_id':'count_30_cart'},inplace = True)
labels.head()

3.3 近30天活跃天数

#对用户进行分组,统计活跃的天数,包括浏览、收藏、加购、购买
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':'count_30_active'},inplace=True)
labels.head()

4、7天用户行为


本维度分析以2014/12/18作为最后一天去分析
4.1 近7天购买次数

df_near_7 = df[df['date']>datetime.strptime('2014-12-11','%Y-%m-%d')]
df_near_7_buy = df_near_7[df_near_7['behavior_type'] == 4].groupby('user_id').item_id.count().reset_index()
df_near_7_buy.rename(columns = {'item_id':'count_7_buy'},inplace = True)
labels = pd.merge(labels,df_near_7_buy,how = 'left',on = 'user_id')
labels.head()

4.2 近7天加购次数

df_near_7_cart = df_near_7[df_near_7['behavior_type'] == 3].groupby('user_id').item_id.count().reset_index()
df_near_7_cart.rename(columns = {'item_id':'count_7_cart'},inplace = True)
labels = pd.merge(labels,df_near_7_cart,how = 'left',on = 'user_id')
labels.head()

4.3 近7天活跃次数

counts_7_active = df_near_7.groupby('user_id')['date'].nunique()
labels = pd.merge(labels,counts_7_active,how='left',on='user_id')
labels.rename(columns={'date':'count_7_active'},inplace=True)
labels.head()

5.最后一次行为距今天数(今天取2014/12/18)
5.1 上次浏览距今天数

#5.1 上次浏览距今天数
day_browes = 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,day_browes,how = 'left',on = 'user_id')
labels.rename(columns = {'date':'day_browes'},inplace = True)

5.2 上次加购距今天数

#5.2 上次加购距今天数
day_cart = df[df['behavior_type']== 3].groupby('user_id').date.max().apply(lambda x:(datetime.strptime('2014-12-19','%Y-%m-%d')-x).days)
labels = pd.merge(labels,day_cart,how = 'left',on = 'user_id')
labels.rename(columns = {'date':'day_cart'},inplace = True)

5.3 上次购买距今天数

#5.3 上次购买距今天数
day_buy = df[df['behavior_type']== 4].groupby('user_id').date.max().apply(lambda x:(datetime.strptime('2014-12-19','%Y-%m-%d')-x).days)
labels = pd.merge(labels,day_buy,how = 'left',on = 'user_id')
labels.rename(columns = {'date':'day_buy'},inplace = True)

6.最近两次购买间隔天数

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()
labels = pd.merge(labels,interval_buy,how = 'left',on = 'user_id')
labels.head()

7.是否有商品浏览未下单

#取出浏览未购买的数据
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 = ['browes','buy']
#nall值填充0
browse_not_buy.fillna(0,inplace = True)
#如果有浏览未购买的将browse_not_buy填充为1
browse_not_buy.loc[(browse_not_buy['browes'] > 0) & browse_not_buy['buy'] == 0,'browes_not_buy'] = 1
#统计用户有多少个商品浏览未购买
browse_not_buy = browse_not_buy.groupby('user_id').browes_not_buy.sum().reset_index()
labels = pd.merge(labels,browse_not_buy,how = 'left',on ='user_id')
#如果有浏览为购买的用户标签改为'是'
labels['browes_not_buy'] = labels['browes_not_buy'].apply(lambda x:'是' if x>0 else '否')
labels.rename(columns = {'browes_not_buy':'browse_not_buy'},inplace = True)

8.是否有商品加购未下单

#取出加购但未下单的数据
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']
#对nall值进行填充
cart_not_buy.fillna(0,inplace = True)
#如果有加购未购买的将browse_not_buy填充为1
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 '否')

9、用户属性标签
9.1 是否复购用户

#提取购买用户的数据,并根据用户进行分组,统计购买次数
buy_again = df[df['behavior_type'] == 4].groupby('user_id').time.count().reset_index()
buy_again.rename(columns = {'time':'buy_again'},inplace = True)
labels = pd.merge(labels,buy_again,how = 'left',on = 'user_id')
#如果购买次数大于1则为复购用户
labels['buy_again'] = labels['buy_again'].apply(lambda x:'是' if x > 1 else '否' if x == 1 else  '未购买')
labels.head()

9.2 访问活跃度

#对count_30_active进行分组,统计访问次数
user_active_level = labels['count_30_active'].value_counts().sort_index(ascending = False)
#进行绘图得到趋势图
plt.figure(figsize=(10,5))
user_active_level.plot(title='30天内访问天数与访问人数的关系',fontsize=18)
plt.ylabel('访问人数',fontsize=14)
plt.xlabel('访问天数',fontsize=14)

总体上看,访问天数多的访客比访问天数少的访客数量多,且以20次左右为拐点,因此定义访问天数小于20次的为低活跃,访问天数大于等于20次的定义为高活跃。

#定义活跃度大于20则为高活跃度用户
labels['buy_active_level'] = '高'
labels.loc[labels['count_30_active']<=19,'buy_active_level'] = '低'

9.3 购买的品类是否单一

#提取购买的数据,并根据user_id进行分组,对购买类目进行统计
buy_sinple = df[df['behavior_type'] == 4].groupby('user_id').item_category.nunique().reset_index()
buy_sinple.rename(columns = {'item_category':'buy_sinple'},inplace = True)
labels = pd.merge(labels,buy_sinple,how = 'left',on = 'user_id')
labels['buy_sinple'].fillna(-1,inplace = True)
#判断技术是否大于1
labels['buy_sinple'] = labels['buy_sinple'].apply(lambda x:'否' if x>1 else '是' if x == 1 else '未购买')

9.4 用户价值分组

#获取标签统计值day_buy得到距今购买天数,并进行统计计数
last_buy_days = labels['day_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)

可以看出大于8天为低

labels['buy_days_level'] = '高'
labels.loc[labels['day_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)
#删除buy_days_level
labels.drop(['buy_days_level','rfm_value'],axis=1,inplace=True)
#统计rfm各个值的情况
labels['rfm'].value_counts()
# 保存数据到数据库中
#将数据存入数据库
engine = create_engine('mysql://root:mima@localhost:3306/datafrog_study?charset=gbk')
labels.to_sql('profile_user_labels',con = engine,if_exists='replace', index=False)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容