python数据分析项目之2 淘宝电商用户行为分析(转化漏斗与RFM模型)

参考:https://zhuanlan.zhihu.com/p/82130467

提出问题及本项目思路

数据预处理

#数据处理包
import pandas as pd
import numpy as np

#数据可视化
%matplotlib inline
import matplotlib.pyplot as plt
import seaborn as sns
from pyecharts import options as opts
from pyecharts.charts import Bar,Pie
from pyecharts.globals import ChartType, SymbolType

#时间处理包
import datetime
import time

#字体设置
plt.rcParams['font.sans-serif']=['SimHei']
df0=pd.read_csv('D:tianchi_mobile_recommend_train_user.csv',)
df0.info() #查看数据类型用df.dtypes
1.PNG

数据集一共12312542个值,user_geohash列的缺失值8402567,直接删除该列并不影响;本项目选取前1000000条数据进行分析

df1=df0.head(100000)
df1.info()
2.PNG
df1.head()
3.PNG
df1['behavior_type']=df1['behavior_type'].astype(str).map({
    '1':'pv',
    '2':'buy',
    '3':'cart',
    '4':'fav'})
    
#'behavior_type'列中的1-4,分别表示点击pv、购买buy、加购物车cart、喜欢fav
df1.head()
4.PNG
df1.drop_duplicates(subset=['user_id','item_id','time'],keep='first',inplace=True)
df1.info()
#重复值去除:本项目根据的是['user_id','item_id','time']来去重的【重复项1000000-913553】
5.PNG
df1['time']=pd.to_datetime(df1['time'])  #将time列,由str转换为时间格式
df1.head()
6.PNG
#后续分析维度:周几、几点,所以要建立相关新列来存放具体的时间
df1['week']=df1['time'].dt.weekday  #date.weekday()返回的0-6代表周一到周日
df1['day']=df1['time'].dt.day
df1['hour']=df1['time'].dt.hour
df1.head()
7.PNG
#将time列,分拆出date列并单独存放
df1['date']=df1['time'].astype(str).str.split(' ').apply(lambda x :x[0])
df1['date']=pd.to_datetime(df1['date'])
df1.info()
8.PNG

数据分析

二级标题

#一周活跃时间段:绘图

df1.groupby('week')['user_id'].count().plot()#date.weekday()返回的0-6代表周一--到周日
9.PNG
#一天时间段活跃度分布
df1.groupby('hour')['hour'].count().plot()
10.PNG

PV和UV的分析

#PV和UV的分析

df1.groupby(['date'])['user_id'].count().plot()
11.PNG
df1.groupby(['date','user_id']).count().reset_index().groupby('date')['user_id'].count().plot()
12.PNG
#用户PV和UV对应的小时活跃度
df1.groupby('hour')['user_id'].count().plot()
13.PNG
df1.groupby(['hour','user_id']).count().reset_index().groupby('hour')['user_id'].count().plot()
14.PNG
#用户不同行为的时间活跃度

import matplotlib.pyplot as plt
plt.figure(figsize=(8,5))
#plt.plot(df1.groupby(['behavior_type'])['hour'].value_counts()['pv'].sort_index())
plt.plot(df1.groupby(['behavior_type'])['hour'].value_counts()['cart'].sort_index(),label = 'cart')
plt.plot(df1.groupby(['behavior_type'])['hour'].value_counts()['fav'].sort_index(),label = 'fav')
plt.plot(df1.groupby(['behavior_type'])['hour'].value_counts()['buy'].sort_index(),label = 'buy')

plt.legend()
plt.show()
#可以看出除了pv比较高,其它的行为都相差不大,用户的转化不高,我们接下来看看转化率
15.PNG
#用户购买的行为频数分布(用户购买次数分布)
df1[df1['behavior_type']=='buy'].groupby('user_id')['behavior_type'].count().reset_index().groupby('behavior_type')['user_id'].count().plot()
17.PNG
import seaborn as sns

freq=df1[df1['behavior_type']=='buy'].groupby('user_id')['behavior_type'].count()
sns.distplot(freq,kde=False)
plt.title('用户购买次数分布')
18.PNG
df1[df1['behavior_type']=='buy'].groupby('user_id')['behavior_type'].count().reset_index().groupby('behavior_type')['user_id'].count().head(20)
19.PNG
  • 购买次数集中在1-7之间的均超过百人。用户购买欲望还可以刺激,可以利用各种补贴、活动、推荐等来提高消费次数。

用户行为转化漏斗

from pyecharts import options as opts
from pyecharts.charts import Bar,Pie
from pyecharts.globals import ChartType, SymbolType
from pyecharts.charts import Funnel
from pyecharts.charts import Bar  #正确的引用方式

Funnel_behavior=df1.groupby(['behavior_type'])['user_id'].count().reset_index().rename(columns={'user_id':'Count'}).sort_values(by='Count',ascending=False)
value=Funnel_behavior['Count'].tolist()
x=Funnel_behavior['behavior_type'].tolist()

c=Funnel()
c.add('',[list(z) for z in zip(Funnel_behavior['behavior_type'],Funnel_behavior['Count'])],label_opts=opts.LabelOpts(position="inside"))
c.set_global_opts(title_opts=opts.TitleOpts(title="用户行为转化漏斗"))
c.render_notebook()
16.PNG
  • 用户行为pv到cart的转化率极低(仅3%=25792 / 862526),想要提高转化率至少应该提高用户加入购物车的概率,说明推荐商品的准确率有点低,提高推荐精准率;
  • 用户行为cart到buy达到了65%(=17164 / 25792),说明用户加入购物车后、购买率还是挺高的。

日平均用户消费金额

#因为没有金额,所以本项目添加随机产生的金额上去
random_price=[np.random.randint(0,1000) for i in range(len(df1['user_id']))]
df1['product_price']=pd.Series(random_price)
#对缺失值进行填充
df1['product_price'].fillna(df1['product_price'].mean(),inplace=True)
#np.random.randint(0,1000) 会产生空值??

Arppu=df1[df1['behavior_type']=='buy'].groupby('date').agg({'product_price':'sum','user_id':'count'})
#Arppu.apply(lambda x :round(x['product_price']/x['user_id']),axis=1).plot()

c=Bar()
c.add_xaxis(Arppu.index.tolist())
c.add_yaxis('ARPPU平均每付费用户收入',Arppu.apply(lambda x :round(x['product_price']/x['user_id']),axis=1).tolist())
c.render_notebook()
20.PNG
  • 因为随机产生的金额而非真实数据,故上图整体波动不大

RFM模型

rfm=df1.pivot_table(index='user_id',
                values=['date','item_id','product_price'],
                aggfunc={
                    'date':'max',
                    'item_id':'count',
                    'product_price':'sum'
                })

rfm.head()
21.PNG
#将R转化为天数
rfm['R']= -(rfm['date'] - rfm['date'].max())/np.timedelta64(1,'D')
rfm.rename(columns={'item_id':'F','product_price':'M'},inplace=True)
rfm.head()
22.PNG
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':'重要发展客户',
        '110':'一般价值客户',
        '010':'一般保持客户',
        '100':'一般挽留客户',
        '000':'一般发展客户' 
    }
    result=d[label]
    return result
rfm['label'] = rfm[['R','F','M']].apply(lambda x : x-x.mean()).apply(rfm_func,axis=1)
#lambda x :rfm_func(x)
rfm.head()
23.PNG
rfm_data=rfm.groupby('label')['R'].count().reset_index().rename(columns={'R':'peoplecount'})
rfm_data
24.PNG
#绘制饼图
from pyecharts.charts import Page,Pie
x = rfm_data['label'].tolist()
y = rfm_data['peoplecount'].tolist()

c=Pie()
c.add('',[list(z) for z in zip(x, y)],radius=["50%", "70%"])
c.set_global_opts(title_opts=opts.TitleOpts(title="Pie-基本示例"),legend_opts=opts.LegendOpts(orient="vertical", pos_top="15%", pos_left="2%"))

c.set_series_opts(label_opts=opts.LabelOpts(formatter="{b}: {c}"))
c.render_notebook()
25.PNG

复购率

data_rebuy = df1[df1['behavior_type']=='buy'].groupby('user_id')['time'].apply(lambda x :len(x.unique()))
#data_rebuy为找出每个用户有消费行为的天数
print('复购率:',round(data_rebuy[data_rebuy>=2].count()/data_rebuy.count(),2))

复购率: 0.65

最受欢迎的商品类目(item_category)与购买率

##按“类目item_category ”统计点击量pv,更改Series名字为'pv_category'
pvtop=df1[df1['behavior_type']=='pv']['item_category'].value_counts().sort_values(ascending=False)
pvtop.name='pv_category'

#按“类目item_category ”统计购买量buy,更改Series名字为'buy_category'
buytop=df1[df1['behavior_type']=='buy']['item_category'].value_counts().sort_values(ascending=False)
buytop.name = 'buy_category'

# 合并(匹配 concat ,axis=1,按行拼接)并绘制散点图:
cattop=pd.concat([pvtop,buytop],axis=1,sort=False).fillna(0)
cattop.plot.scatter(x='pv_category',y='buy_category')  
#给series命名是为了在scatter绘图里面x,y坐标轴用

26.PNG

大部门商品类目并没有吸引购买者:
可以看出分布集中在左下角,即大部分商品类目‘item_category’的转化率(pv_category / buy_category)在2%之间。

最受欢迎的商品(item_id)与购买率

#按“商品(item_id)”统计点击量pv,更改Series名字
pv_p_top=df1[df1['behavior_type']=='pv']['item_id'].value_counts().sort_values(ascending=False)
pv_p_top.name='pv_product'

#按“商品(item_id)”统计购买量buy,更改Series名字
buy_p_top=df1[df1['behavior_type']=='buy']['item_id'].value_counts().sort_values(ascending=False)
buy_p_top.name = 'buy_product'

# 合并(匹配 concat ,axis=1,按行拼接)并绘制散点图:
producttop=pd.concat([pv_p_top,buy_p_top],axis=1,sort=False).fillna(0)
producttop.plot.scatter(x='pv_product',y='buy_product')  
#给series命名是为了在scatter绘图里面x,y坐标轴用
27.PNG

最受欢迎的商品浏览量在0-200之间、购买数在0-10之间,转化率是5%,用户的购买转化率较低,可以考虑提升一下商品的文案、图片等方面。

点击/购买前十的商品/类目及其购买量

## 点击量前十的商品类目及其购买量
pd.DataFrame(pvtop[:10])  # pv前十的类目,并转化为数据框df
28.PNG
# join按购买量排序的类目
pd.DataFrame(pvtop[:10]).join(buytop)#或者 df.join(pd.DataFrame(buytop))
29.PNG
#购买量前十的商品类目及其点击量

pd.DataFrame(buytop[:10]).join(pvtop)
30.PNG
#点击量pv前十的商品id和购买量

pd.DataFrame(pv_p_top[:10]).join(buy_p_top)
31.PNG

点击量大、但没人购买的商品(转化率非常不好),可以检查一下该商品的包装、价格等因素

#购买量buy前十的商品id和点击量

pd.DataFrame(buy_p_top[:10]).join(pv_p_top)
32.PNG

总结与结论:

1)基于RFM模型,根据不同类型用户精准运营,进行个性化推荐;

2)根据时间维度进行有效地拉新促活活动,以及老用户的访问。根据复购率来刺激用户的持续消费,根据留存监控用户的持续用户行为,防止流失并且对用户行为给与一定的刺激;

3)对高价值用户需要提供优惠策略使其保持活跃度,针对不同用户行为人群制定针对性策略从而刺激进一步的用户行为,针对不活跃用户以及大部分的低购买用户采取相应措施刺激或者提高活跃度。

4)针对一些转化率低的商品,做好包装、价格、图片等因素的改善,提高转化率

PV和UV的分析

五级标题
  • 列表第一项
  • 列表第二项
  1. 有序列表第一项
  2. 有序列表第二项
    标题
    [图片上传失败...(image-f4016e-1579525662317)]
    斜体
    粗体

引用段落

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容