## 条件
这是我分析的条件,不同情况就举一反三吧
1.游戏环境:
很标准的放置卡牌体系,如afk
2.养成资源:
英雄+装备【饰品符文等等】
3.相对靠谱的数值体系:
对应的数值策划都已经给了战力,战力在一定意义上能够描述养成程度
对应的运营给了vip标准,vip等级在一定程度上能够反映玩家的付费程度
分析目的
- 主要是为了看不同vip下玩家的养成程度,在一个标准的放置卡牌体系中,玩家的战力和养成程度是线性正相关的
- 如果系统策划把某些关卡、副本、功能和战力挂钩了,那分析【付费-战力】,是非常有必要的
- 如果数据反映出的战力表现得失常,我们不能马上就断定游戏生态失常,还需要进一步找原因,也可能是样本太小导致的
- 最终如果发现生态真的失常,可能系统策划和数值策划需要接入调整,运营上也需要采取风控运营 的策略,避免失常的这一部分玩家产生【不充钱也能打氪佬】和【充钱居然不能变强】的体验
- 当然不是非要基于vip维度来看,等级、竞技场段位都可以的,不同维度分析出来的东西也不同,方法是类似的
数据清洗
1.首先肯定要筛选掉噪点,这里的噪点通常是英雄品质和英雄等级之类,因为你肯定不想把玩家囤积的狗粮也算进来,尽肯能剔除狗粮的影响,才更接近真相
2.等级过低的玩家也可能需要提出,比如0-2级的这种,还在新手期的玩家数据,你分析了没意义,也是噪点
数据分析
1.首先做数据透视,索引字段就是【vip】,统计字段是【战力】,算法就是常规的描述统计,中位数、均值、众数,一键三连,我这里用的是pandas的group by,excel玩家就用透视表做,不难的
2.【重点】除了三连,还需要统计偏度,找出哪个vip下,玩家战力分布处于失常状态。偏度的定义网上可以搜到,偏度的计算方法,我这里
偏度>0.5,越大,说明这个vip下的用户,实力偏弱的人多
偏度<-0.5,越小,说明这个vip下的用户,实力偏强的人多
3.除偏度以外,有时候也需要看极值,假如出现vip2的战力极值大于vip5,一定是有问题的,中位数、均值、众数也是做辅助判断的依据
4.找出失常的vip后,需要通过极值去找到那个具体失常的人,看看他的所有数据,对比他所在vip下的标准数据,找出具体失常的点,单纯战力分析一定是片面的,因此必须结合其他数据分析结果一起看,才能接近真相
根据我的经验,vip低的人群,战力偏度通常是小于-0.5,或者服从正态分布的
我们通常更关注vip高的这一部分
如果vip高,且偏度远大于0.5,说明里面小部分氪佬实力超前,需要关注这部分人充值金额是否能够打出这个实力【风控运营】
如果vip高,且偏度远小于-0.5,说明氪佬里面有明显掉队的,需要gs介入带一带,或者vip客服安抚【防止大R流失】
源码示例
直接复制过去大概没法用的,并且这个脚本只是项目的一部分,看个思路吧
import sanguo.data.gamedata
import pandas as pd
import numpy as np
import datetime
data = pd.read_excel('C:\\Users\\mayn\\Desktop\\三国\\data\\诙谐三国-hero.xlsx')
hero = sanguo.data.gamedata.hero
hero_name = hero.loc[:,['英雄ID','英雄名称']]
df = pd.merge(data,hero_name,left_on='hid',right_on='英雄ID',how='left')
def vip_zhanli():
list1 = []
max_zhanli_list = df.groupby('vip')['战力'].max('战力').values
for i in max_zhanli_list:
a = df[df['战力'] == i]
list1.append(a)
zhanli_analyse = pd.concat(list1)
zhanli_analyse['战力中位数'] = df.groupby('vip')['战力'].median('战力').values
zhanli_analyse['战力均值'] = df.groupby('vip')['战力'].mean('战力').values
zhanli_analyse['战力众数'] = df.groupby('vip')['战力'].agg(lambda x: np.mean(pd.Series.mode(x))).values
##这个众数算法比较特殊,由于pandas的group by不能算众数,所以用agg方法,引用 pd.Series.mode() 然后区众数的平均
#众数暂时不用了
zhanli_analyse['偏度'] = df.groupby('vip')['战力'].skew().values
# (1)Skewness = 0 ,分布形态与正态分布偏度相同。
# (2)Skewness > 0 ,正偏差数值较大,为正偏或右偏。长尾巴拖在右边,数据右端有较多的极端值。
# (3)Skewness < 0 ,负偏差数值较大,为负偏或左偏。长尾巴拖在左边,数据左端有较多的极端值。
# (4)数值的绝对值越大,表明数据分布越不对称,偏斜程度大
zhanli_analyse = zhanli_analyse.iloc[:,[2,4,12,13,15]]
zhanli_analyse.columns = ['vip','最高战力','战力中位数','战力均值','偏度']
return zhanli_analyse
def vip_hero(quantile_=0.8):
list_ = []
for i in np.sort(df['vip'].unique()):
## unique()相当于sql 里面的distinct ,sort是排序
vip_hero_count = pd.pivot_table(df[(df['vip']==i) & (df['星级']>=2)],index='英雄名称',values='uid',aggfunc='count')['uid'].reset_index()
## 筛选 vip 等于 i, 星级大于2的英雄,透视表按vip,计数,重新索引
pop_hero = vip_hero_count[vip_hero_count['uid'] >= vip_hero_count['uid'].quantile(quantile_)]
pop_hero = pop_hero.copy()
## 虽然不知道为什么,但是不copy就报错
pop_hero['vip'] = np.copy(i)
order = ['vip','英雄名称','uid']
pop_hero = pop_hero[order]
pop_hero.columns = ['vip','英雄名称','数量']
list_.append(pop_hero)
pop_hero_df = pd.concat(list_)
return pop_hero_df
def vip_zhuangbei():
df_avg_zhuangbei = df.copy()
df_avg_zhuangbei['装备分'] = df_avg_zhuangbei[['装备1','装备2','装备3','装备4']].apply(lambda x:x.sum(),axis =1)
## 装备分等于四个装备值的平均,只能用apply方法做
zhuangbei = df_avg_zhuangbei.groupby('vip')['装备分'].max('装备分').reset_index()
zhuangbei.columns = ['vip','极限装备分']
zhuangbei['中位数'] = df_avg_zhuangbei.groupby('vip')['装备分'].median('装备分').reset_index()['装备分'].values
zhuangbei['平均数'] = df_avg_zhuangbei.groupby('vip')['装备分'].mean('装备分').reset_index()['装备分'].values
zhuangbei['偏度'] = df_avg_zhuangbei.groupby('vip')['装备分'].skew().reset_index()['装备分'].values
return zhuangbei
def to_excel():
xlsx = pd.ExcelWriter("C:\\Users\\mayn\\Desktop\\三国\\数据分析\\战力-英雄-装备-分析%s.xlsx"%str(datetime.date.today()))
vip_zhanli().to_excel(xlsx, sheet_name="战力分析", index=False)
vip_hero(quantile_=0.8).to_excel(xlsx, sheet_name="英雄分析", index=False)
vip_zhuangbei().to_excel(xlsx, sheet_name="装备分析", index=False)
print("保存完成")
xlsx.close()
# to_excel("歌手活跃用户%s.xlsx"%str(datetime.date.today())