美文网首页
玩家的等级成长曲线

玩家的等级成长曲线

作者: Houtasu | 来源:发表于2020-12-03 09:54 被阅读0次

    在一款游戏中,数值策划会在游戏的设计阶段,规划玩家的等级成长的曲线,
    包括每个等级需要的资源数,不同付费级别的玩家在每个等级的驻留时间等。
    在游戏上线后,就需要去获取玩家的实际的成长曲线,和策划的设计曲线做对比,看看有没有偏差之类的。
    本篇主要讲怎么去分析玩家的等级成长曲线,并绘制图形。
    首先确定做这个分析一共需要的数据:
    时间戳,玩家的注册时间,玩家id,各个时间戳下的游戏内等级和玩家的付费等级。
    随便在日志中找个经常被触发的命令,带有时间戳和当前等级就行。
    比如下面这种:


    然后需要找到玩家的注册时间,得到每一行数据对于该玩家的注册时间的天数差,
    再去个重就可以得到玩家的游戏天数和等级的数据了。

    查询天数差的sql如下
    SELECT
      item.uid,
      item.level,
    --当前时间减去注册时间得到天数差--
      datetime_diff(datetime(item.ts),  datetime(reg.ts), DAY) AS day
    FROM
      `cmd表` AS item
    LEFT JOIN
      `regist表` AS reg
    ON
      reg.uid = item.uid
    WHERE
      DATE(item.ts, '+08') BETWEEN "2020-10-12"  AND "2020-11-26"
    GROUP BY
      1,  2,  3
    ORDER BY
      1,  2
    

    用pandas找到玩家每天的最大等级

    #按照uid和day分组,取level的最大值的索引,再根据索引筛选数据,同时也是去除重复的数据
    level = level.loc[level.groupby(by=['day','uid'])['level'].idxmax()]
    

    使用pivot_table转换下行列

    le = level.pivot_table(index='uid', columns='day', values='level')
    
    image.png

    这样就得到了玩家等级随天数的变化情况。
    但是这样还有两个问题, 第一个是上图第一个框中的,在两天数据中有缺失值。
    这表示玩家在这天没有触发过这条命令,如果你选的是登陆必触发的命令则说明玩家在当天没有登陆。
    这种可以直接按照上一次的等级填充。
    然后是第二种情况,玩家直接弃坑了,这种就不需要填充数据。
    因为弃坑后他的等级是不会变的,如果纳入统计会很大的拉低整体的数据值。
    所以综合下就是在玩家弃坑前的缺失值要填充,弃坑后就不填充。
    那么直接从后往前遍历,找到第一个不为空的数据,就是玩家的弃坑时间,然后填充前面的值就好了。

    def fill_level(row):
        for i in range(45,-1,-1):
             if not np.isnan(row.iloc[i]):
                return row[:i+1].fillna(method='ffill')
    le = le.apply(fill_level, axis=1)
    

    现在拿到了基本的玩家等级随天数变化的数据,然后和充值表连表,找到每个玩家的充值等级。

    SELECT
    uid, sum(value ) as total_buy
    FROM
      `充值表` 
    where server = '28'
    group by 1
    

    拿到玩家的充值数据后,按不同金额分段,比如按照100内为小R,100-1000为中R,1000以上为大R

    buy['r'] = pd.cut(buy['total_buy'], [0, 100,1000,np.inf],
                      right=False, labels=['R', 'SR', 'SSR'])
    

    看下各个等级有多少人:

    buy['r'].value_counts()
    
    R      184
    SR      42
    SSR      9
    

    然后把我们的等级变化表和充值表连起来

    leb = pd.merge(le, buy[['uid','r']], how='left', on='uid')
    

    连表后充值玩家的等级已经和uid对应起来的,但是未充值玩家的这一列仍是空值,所以需要填充一下。
    由于上面我们分等级的时候用了pd.cut,这一列的类型变为了category,直接使用fillna是会报错的。
    因为category只允许插入分类中已有的值。
    具体来说,在上面的labels中有['R', 'SR', 'SSR']这三个类型,那么fillna的值只能填这三个类型。
    所以需要先插入一个未充值玩家的类型,在使用fillna填充。

    # 在分类中插入N类型,再使用fillna做填充
    leb['r'].cat.add_categories(['N'], inplace=True)
    leb['r'].fillna('N', inplace=True)
    leb['r'] = leb['r'].astype('str')
    
    leb['r'].value_counts()
    
    N      2045
    R       138
    SR       31
    SSR       8
    

    然后我们把每一个等级的数据提取出来,准备绘图

    leN = leb[leb['r']=='N'].copy()
    leR = leb[leb['r']=='R'].copy()
    leSR = leb[leb['r']=='SR'].copy()
    leSSR = leb[leb['r']=='SSR'].copy()
    

    这里使用箱线图,因为箱线图可以表示一个数据的分布,再加上平均值,可以较好的展示真实的数据。

    plt.figure(figsize=(24, 9), dpi=80)
    t = le.drop(['uid', 'r'], axis=1)
    lm = t.mean()
    # 这里索引不加1的话,折线图的X轴会和箱线图的X轴是对不上,具体我也不知道为啥。。。
    lm.index += 1
    lm.plot(c='g', label=' N average line')
    t.boxplot(color='r')
    plt.legend()
    

    现在拿到了玩家的成长数据了,接下来把策划设计的线加上就可以了。

    plt.figure(figsize=(24, 9), dpi=80)
    t = le.drop(['uid', 'r'], axis=1)
    lm = t.mean()
    # 这里索引不加1的话,折线图的X轴会和箱线图的X轴是对不上,具体我也不知道为啥。。。
    lm.index += 1
    lm.plot(c='g', label=' N average line')
    # 根据策划给出的等级成长规划得到的数据
    N_up_line.plot(c='b', label='N design line')
    t.boxplot(color='r')
    # 设置标题
    plt.title('all user')
    # 画出线段说明,下图左上角的那个
    plt.legend()
    plt.show()
    

    剩下的就是画出不同充值等级的玩家的图表了,代码都是一样的,
    改下t = le.drop(['uid', 'r'], axis=1)就可以了。
    可以从图中看出,前期玩家至少有一半是没跟上策划的规划线的,那么就可以从其他方便查找一下没跟上的原因,然后采取一些手段优化玩家的成长体验。
    箱线图的具体说明如上下限、异常值怎么算的,请自行百度。
    -- end --

    相关文章

      网友评论

          本文标题:玩家的等级成长曲线

          本文链接:https://www.haomeiwen.com/subject/dhtmwktx.html