python实战用户增长Cohort分析

大家好,我是Peter~

本文中介绍的是一种数据分析方法:群组分析Cohort Analysis。

群组分析是用于研究用户行为和提高增长的分析思路。在本文中,将结合一个数据集Python来实现该分析方法。

https://www.philosophicalhacker.com/post/better-cohort-analysis/

本文数据集下载地址:https://www.kaggle.com/mkechinov/ecommerce-events-history-in-cosmetics-shop

什么是群组分析

群组分析Cohort Analysis,重点就是群/组,它是一种利用用户分层和用户建模的方法,主要分析的是相同用户群体随着时间延续的变化发展情况。我们需要将获取到的全部用户分成一个个的组或者簇群,这样的群或组的分层方式可以是日期、渠道或者其他特定的用户为来划分。总之,我们可以按照实际的需求和维度来进行用户分层。

通过群组分析,我们可以看到不同组别的留存情况。群组分析Cohort Analysis图表和留存曲线是最常用的留存工具。这些图表主要是告诉我们用户在我们产品的中的参与度如何,留存率是怎样的情况,同时还可以分析用户新增速度是否达到我们的要求。

目前市面上很多的BI工具都可以绘制群组分析的图表和留存曲线,比如GrowingIO、神策大数据系统、PowerBI等。但是,如果想自定义一些分组或分群的维度,使用Python还是不二选择。

Cohort 分析使用场景

  1. 用户留存率分析
  2. 用户流失率分析
  3. 用户转化率分析
  4. 广告转化率分析

上面是很常见的使用场景,还可以进行其他场合的延伸,比如电商网站用户的交易支付数据,不同周期内获取的用户在交易频次、客单价等的比较分析

用户留存

用户留存指的是随着时间延续,用户在某个周期内的存在情况。为什么要看留存?

  • 了解一个渠道的质量:通常是日留存,衡量用户的短期活跃情况
  • 观察整体的情况:用周留存或者月留存,衡量用户在平台上的黏性

留存又分为次日留存、7日留存、14留存等。下面通过一个案例来说明常见的7日留存计算规则。

问题:如何计算产品的7日留存?

image

算法1-7日日留存

第一种算法是:第7天活跃人数 / 第1天活跃人数 * 100%

image

算法2-7日内留存

第二种算法是:第2天~第7天去重后/第1天*100%

image

算法3-不同定义的7日日留存

上面的算法1中是把当前日直接记为Day1,还有一种计算方法将当前日当做Day0,然后再开始计算;

image

举例说明一下算法3的使用,比如DAU=10刚好是星期2产生的数据:

  • 如果使用算法1,7日日留存=下周1的数据/本周2的数据(10)
  • 如果使用算法2,7日日留存=下周2的数据/本周2的数据(10)

说明:算法3在一定程度上能够巧妙避开星期级别的影响

image

3种留存算法

image

本文数据

导入数据

本文中使用的一份数据集是从kaggle下载,主要是包含事件发生时间、类型(阅览、加购、移除购物车和购买)、产品ID、分类ID、产品编码、品牌、价格、用户ID、用户会话,总共7个属性

image
import numpy as np 
import pandas as pd 
import datetime as dt 
 
import matplotlib.pyplot as plt
import seaborn as sns
 
#设置汉字格式:Trebuchet MS, Tahoma, Verdana, Arial, Helvetica,SimHei 中文的幼圆、隶书等等

# 解决中文无法显示问题
plt.rcParams['font.sans-serif']=['Songti SC']   
# 解决保存图像中负号'-'显示为方块问题
plt.rcParams['axes.unicode_minus'] = False  

数据探索

主要查看的是数据类型、数据的行列数看大小、数据的缺失值情况

df.dtypes  # 数据类型

# 结果
event_time        object
event_type        object
product_id         int64
category_id        int64
category_code     object
brand             object
price            float64
user_id            int64
user_session      object
dtype: object
  
df.shape  # 数据的行列数
# 结果
(3533286, 9)

df.isnull().sum()   # 字段缺失值情况
# 结果
event_time             0
event_type             0
product_id             0
category_id            0
category_code    3474821    # 缺失值严重
brand            1510289
price                  0
user_id                0
user_session         779
dtype: int64

数据清洗

主要操作是挑选数据中价格大于和去重操作:

image

数据处理

在本文的案例中,群组分析是按照首次访问的时间和每次的访问来计算时间间隔,从而来计算留存情况,具体步骤为:

  • 计算每个用户的首次访问时间min_day
  • 记录后续每次访问时间和首次访问时间的间隔day_gap
  • 因为是12月份的电商数据,我们将一个月分成10份,时间周期为3天

因为上面的两个因素都是和时间相关,所以必须导入Python中强大的datetime库来处理时间处理的需求。

1、获取event_time中的时间:年月日

def get_time(datetime):
  """
  函数作用:获取时间中的年月日
  """
    event_time = datetime.strip(" UTC")  # 传进来的参数去掉 UTC部分
    # dt表示datetime库
    event_time = dt.datetime.fromisoformat(event_time)  # 生成一个YYYY-MM-DD的date对象
    y = dt.date(event_time.year,event_time.month,event_time.day)  # 取出年月日
    return y
  
df2["event_day"] = df2["event_time"].apply(get_time)
df2

[图片上传失败...(image-b1f53e-1624450391023)]

2、根据每个用户user_id来确定最早时间

# 用户本月的最早登陆时间确定
grouping = df2.groupby("user_id")["event_day"]
grouping
image
df2["min_day"] = grouping.transform("min")
df2.head()
image

3、计算访问日event_day和最早访问时间的间隔

# 计算用户当日访问event_day和最早访问时间min_day之间的时间间隔
# 3为假定的用户分组访问周期

df2["day_gap"] = (((df2["event_day"] - df2["min_day"]) // 3) + dt.timedelta(days=1)).apply(lambda x:x.days)
df2
image

4、按照首次访问时间和时间间隔来统计用户数

#  按照首次访问时间和下一次访问的间隔,统计用户数
grouping1 = df2.groupby(["min_day","day_gap"])

# 根据用户user_id去重统计每个组的用户数
# grouping1["user_id"].apply(pd.Series.nunique):展示去重的总个数
# grouping1["user_id"].apply(pd.Series.unique): 展示去重之后的具体元素
df3 = grouping1["user_id"].apply(pd.Series.nunique).reset_index()
df3.head()
image

上面表中的数据表示的是和当前的时间间隔分别为1,2,3…的人数分别为17519,2591,2276等

5、生成数据透视表

有了上面分组统计的数据,我们可以生成透视表

# 数据透视部分
df4 = df3.pivot(index="min_day",columns="day_gap",values="user_id")
df4.head()
image

6、改变数据形式:方便最终使用百分比显示数据

一般情况下,我们习惯用百分比来表示用户的留存,很清晰地看到用户的留存比例。首先我们取出第一列的数据(全部行):

image

后面每个数据除以相应日期的第一个数据:

# divide 函数
table = df4.divide(size,axis=0)  # 在行的方向上除以对应size中的值
table.head()
image

保留3位小数,同时改变数据table的索引值:

# 保留3位小数并乘以100
table.round(3) * 100

# 索引重置,只取出年月日,后面的时分秒取消
table.index = table.index.date  

群组分析绘图

绘制群组分析留存热力图:

# 解决中文无法显示问题
plt.rcParams['font.sans-serif']=['Songti SC']   
# 解决保存图像中负号'-'显示为方块问题
plt.rcParams['axes.unicode_minus'] = False  

plt.figure(figsize=(15,8))
plt.title("群组分析留存图")

sns.heatmap(data=table,
            annot=True,
            fmt='.0%',
            vmin = 0.0,
            vmax = 0.2,
            cmap="BuPu_r"
           )
plt.show()
image

从上面的数据中我们可以看到:前6天的留存情况还是很漂亮(颜色较浅,留存率相对较高)。可能原因是这是整个12月份的全量数据,导致了多数的活跃用户会被归类会月初前几天的新增活跃用户。但是数据整体上到了月末,留存占比还是较少,月留存情况并不可观。

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

推荐阅读更多精彩内容