前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >一种计算用户留存的方法

一种计算用户留存的方法

作者头像
木东居士
发布2019-02-28 16:26:33
3.4K0
发布2019-02-28 16:26:33
举报

0x00 概述

用户留存分析是互联网时代常用的一种数据分析方法。而很多快速发展的公司并没有相应的方法论沉淀,这就导致了在计算用户留存的时候会出现下面的一些问题:1)用户留存的定义不明确,不同的研发有自己的理解;2)没有保留计算过程的中间表,数据可复用程度低;3)不同研发的开发习惯不同,导致计算过程和表设计不统一。

鉴于以上问题,本文将指出一种通用的用户留存定义,并提供通用的计算流程以及具体的表结构设计。

0x01 简介

用户留存在不同的业务场景有不同的定义方式,比如说用户注册留存和用户活跃留存等。虽说定义方式不同,但大致思路和计算方式基本相同,本文将以用户活跃留存为例进行说明。

用户留存分析一般会分析两个指标:用户留存数和用户留存率。以 2048年05月12日 的留存分析为例,

  • 20480512的次日留存数 = 20480512日活跃用户 交集 20480513日的活跃用户数
  • 20480512的次日留存率 = 20480512的次日留存数/20480512的总活跃数

在留存分析中,除了次日留存以外,最常用的分析指标是3日留存、7日留存和30日留存。其中7日留存和30日留存可以理解为是周留存和月留存。下面是具体的定义:

  • 3日留存率 = (第1日活跃的用户,在第3日还活跃的用户数)/第1日的活跃用户数
  • 7日留存率 = (第1日活跃的用户,在第7日还活跃的用户数)/第1日的活跃用户数
  • 30日留存率 = (第1日活跃的用户,在第30日还活跃的用户数)/第1日的活跃用户数

0x02 计算

首先说一下用户留存的计算难点在哪里。用户留存计算的时候,每天要刷新之前日期的数据,比如说今天数2048年5月30号,那我们今天要算出这几个指标:20480530当天活跃用户数,20480529的1日留存数,20480527的3日留存数,20480523的7日留存数,以及20480430的30日留存数。并且,这些数据要分别放到对应那一天的报表里面。这就要求我们每天的任务要更新历史某天的数据项。

基于上面说的难点,我们做如下设计。我们讲用户留存的计算设计分为三部分:数据流设计、表结构设计和通用代码设计。

一、数据流和表结构

数据流和表结构可以放在一起讨论,为了简单说明,我设计了最简单能说明观点的表结构。

如下图,是整个计算流程,我们设计了两张表:用户留存中间表和用户留存报表。注意一下用户留存表中的type字段,它表示的用户留存的类型,看注释可知每个取值的含义。

我们设计用户留存中间表的原因是这样可以将中间表提供给数据分析使用,方便用该表和各种数据做交集用户,因此保留了uid的粒度。

用户留存报表使用这种竖表的设计方式,主要是为了考虑每天要修改历史数据的原因。如果用横表(即多个字段分别表示用户当日活跃、1日留存、7日留存等数据),那每天就要重新刷新多天数据分区中的所有数据,使用竖表则会减少很多的计算量并且更容易维护,只需在报表系统中将竖表转成横表展示即可。

二、通用代码设计

按照上面的设计,我们可以设计一套十分简单的代码来计算留存,比如1日、3日、7日和30日留存,可以用同一套代码完成,只要传入参数不同即可。如下是留存中间表的核心代码逻辑,报表的逻辑类似就不再展示。

代码清单1:留存计算通用代码
代码语言:javascript
复制
def _rt_sql(cur_date, user_type):
    '''
    user_type:留存类型,0表示当天活跃,1表示次日留存
    '''
    start_date = dateDelta(cur_date, user_type*-1) # start_date 表示的n日留存的那一天的日期。
    sql = '''
        insert overwrite table 用户活跃天表 partition(p_{start_date}, p_{user_type})
        select 
            {start_date} as ds,
            {user_type} as user_type,
            p_0.uid
        from
            用户活跃天表 p_0 -- 当时的活跃
        join 
            用户留存中间表 p_now -- 今天活跃
        on 
            p_0.uid = p_now.uid
        where p_0.ds = {start_date} and p_0.type = 0
        and p_now.ds = {cur_date}
    '''.format(cur_date=cur_date, user_type=str(user_type), start_date=start_date)
    exec_sql(sql)  ## 封装了执行sql的代码
代码清单2:整体计算逻辑
代码语言:javascript
复制
def _run(cur_date):
    _user_act_sql(cur_date) ## 计算当日活跃的用户,代码就不再写了
    _rt_sql(cur_date, 1) ## 1日留存
    _rt_sql(cur_date, 3) ## 3日留存
    _rt_sql(cur_date, 7) ## 7日留存
    _rt_sql(cur_date, 30) ## 30日留存

OK,通用代码就是这么简单。整体也就是几十行代码的量。

0xFF 总结

用户留存是数据分析常用而且十分简单有效的一种分析方法,但是很多公司对于留存的定义和计算方式都没有形成自己的方法论。比如说留存的定义,有的数据分析理解为连续留存,以7日留存为例,那么7日留存的计算逻辑是第一日活跃,后7日内凡事有活跃的用户都算是7日留存。而另外一些数据分析就会用我们本文中提的用户点留存,即只看第7天当天十分活跃。 然后再辅助于用户流失和回流等指标一同分析。

计算逻辑同样如此,不同的研发在计算留存的时候也使用了不同的方式,这就导致了最终提供给业务方或者其它研发的表十分不宜用。因此本文指出一种常用且比较通用的用户留存计算方式,并提供一套可行的留存计算通用代码,旨在提高开发和数据分析效率,保证数据口径的一致和数据的易用。

写在最后,有两个问题可以考虑一下:

  1. 文中的代码逻辑有很多可以优化的地方,不知道有朋友发觉了吗?
  2. 另外,如果不用计算中间表,只计算最终的报表,有没有十分简洁的Sql实现?
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-10-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 木东居士 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 0x00 概述
  • 0x02 计算
    • 一、数据流和表结构
      • 二、通用代码设计
        • 代码清单1:留存计算通用代码
        • 代码清单2:整体计算逻辑
    • 0xFF 总结
    相关产品与服务
    腾讯云 BI
    腾讯云 BI(Business Intelligence,BI)提供从数据源接入、数据建模到数据可视化分析全流程的BI能力,帮助经营者快速获取决策数据依据。系统采用敏捷自助式设计,使用者仅需通过简单拖拽即可完成原本复杂的报表开发过程,并支持报表的分享、推送等企业协作场景。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档