玩家的充值间隔

2021-03-10  本文已影响0人  Houtasu

现在有需求需要统计不同付费等级玩家的充值间隔差异,
简单来说就是玩家平均隔多久充一笔钱。
这需要对单个玩家统计前后两笔订单时间的差值。
订单原始数据如下结构:


主要就是用户id和该笔订单的时间,现在要做的事就是按照uid分组,再按照时间排序,
然后第二笔时间减第一笔时间,第三笔时间减第二笔时间...,得到所有订单的间隔。
最后再统计这个间隔,求个平均值和中位数什么的。
这个需求看起来很简单,核心其实就是知道要怎么做到下一行减上一行。
在BigQuery中需要用到以前讲过的分析函数
核心就是lag这个函数:文档指路
LAG(ts) OVER (PARTITION BY uid ORDER BY ts )
这个函数可以拿到上一行的数据,然后用date_diff相减就好了。
SELECT
  uid,
  ts,
  LAG(ts) OVER (PARTITION BY uid ORDER BY ts ),
  DATE_DIFF(DATE(ts), DATE(LAG(ts) OVER (PARTITION BY uid ORDER BY ts )), day) AS day
FROM
 充值表
WHERE
  DATE(ts, '+08') BETWEEN "2021-1-1"
  AND "2021-1-31"
ORDER BY
  1,
  2

可以看到上图中fo_就是左边ts的下一行,如果玩家只有一笔充值,那就是null。
拿到间隔后该干嘛就干嘛,没啥好讲的,接下来说说pandas怎么实现这个需求。
核心是shift这个函数,这个函数也可以拿到上一行的数据,
准备来说是偏移量下的数据,不过默认就是上一行。

不过相减前还有先按照uid分组
iap['interval'] = iap.groupby('uid').apply(lambda x:(x['ts'] - x['ts'].shift()).dt.days).reset_index(drop=True)
iap

这一行的东西有点多,详细讲一下。
首先groupby函数用来分组,在调用apply函数对分组内的数据做处理。
lambda是匿名函数,内容不多就不写单独的函数了。
然后是本身和本身的shift()相减,就得到了前后两笔订单的差值。
但这个差值实际是一个timedelta64[ns]的Series。

我们实际需要的是day,这里要用到Series.dt.days属性,文档指路
不过这里有点问题,实际文档里属性的是day而不是days,但是直接调day是会报错的。

这里显示的是TimedeltaProperties,而文档里是搜不到这个关键词的。
不过有pandas.Timedelta.days这个属性,但如果不加.dt而直接掉days也是会报错的。

猜测dt属性会把根据数据内容将该列转为对应的时间类型,这里是转为了Timedelta再调用它的days属性。
然后注意的是我们要把分组后的Series赋给原dataframe,直接赋值是不可以的。
因为groupby后是一个二重索引。

必须要是和原索引相等的Series才能正确赋值。
所以还需要用到reset_index()这个函数。
直接reset_index()会转为一个dataframe。

二级索引会转为两列,但我们只需要序数索引那一列记好了,这里需要用到drop参数,表示是否将不需要的索引删掉。

现在在直接赋值给iap['interval']就没什么问题了。
上一篇 下一篇

猜你喜欢

热点阅读