分析进阶篇(三):通过决策树分析,探明具有哪些行为的用户会是长期用户

案例背景:

《黑猫游戏》相比其他应用,很多用户开始游戏后不久就离开了。

为改善这种情况,通过数据分析探明,开始游戏后,什么样的用户行为能促使用户今后也持续登录游戏,从而帮助改进游戏设计。

由于用户在初期的游戏行为,主要包括3类:战斗、协作、发送消息,那么,通过量化这3类社交行为(每日行为发送次数、每日行为比率、每日行为次数的主成分数据),来参与分析。

同时,如果把所有分析属性放在一起分析,得到的结果可能难以解释。可以通过先将各分析属性和各自的社交行为进行聚类,以得到的类作为自变量。这样,我们就能清楚知道,哪种分析属性用来分析哪种社交行为最能解释模型。

模型的因变量,选择用户一周时间内的登录密度(登陆天数/7)

时间区间的切分——

以用户开始游戏后一周内(0-6天)的行为数据作为自变量,

登陆密度的计算,则通过下一周(7-13天)数据得到。

使用数据:

●DAU:日活数据

●Install:用户安装数据,包括用户属性等

●战斗行为日志:某一天,某个用户,战斗行为发生的次数

●发送消息行为日志:某一天,某个用户,发送消息行为发生的次数

●协作行为日志:某一天,某个用户,协作行为发生的次数

分析流程:加载常用库

import pandas as pd

import numpy as np

import matplotlib.pyplot as plt

%matplotlib inline

import sklearn

import seaborn as sns读入数据

path = 'yourpath/R/sample-data/section9/daily/'

install_path = 'yourpath/R/sample-data/section9/snapshot/install/game-01/2013-09-30/install.csv'

datearray = pd.date_range('2013-06-01','2013-08-31',freq='D')

datedau = pd.date_range('2013-06-01','2013-09-30',freq='D')

from datetime import datetime

dau = pd.DataFrame()

for i in datedau:

date = datetime.date(i)

app_name = 'game-01'

path_small = path

path_pro = f'{path_small}dau/{app_name}/{date}/dau.csv'

data = pd.read_csv(path_pro)

data = pd.DataFrame(data)

dau = pd.concat([dau,data],ignore_index=True,axis=0)

battle = pd.DataFrame()

for i in datearray:

date = datetime.date(i)

app_name = 'game-01'

path_small = path

path_pro = f'{path_small}action/{app_name}/battle/{date}/battle.csv'

data = pd.read_csv(path_pro)

data = pd.DataFrame(data)

battle = pd.concat([battle,data],ignore_index=True,axis=0)

help1 = pd.DataFrame()

for i in datearray:

date = datetime.date(i)

app_name = 'game-01'

path_small = path

path_pro = f'{path_small}action/{app_name}/help/{date}/help.csv'

data = pd.read_csv(path_pro)

data = pd.DataFrame(data)

help1 = pd.concat([help1,data],ignore_index=True,axis=0)

message = pd.DataFrame()

for i in datearray:

date = datetime.date(i)

app_name = 'game-01'

path_small = path

path_pro = f'{path_small}action/{app_name}/message/{date}/message.csv'

data = pd.read_csv(path_pro)

data = pd.DataFrame(data)

message = pd.concat([message,data],ignore_index=True,axis=0)

install = pd.read_csv(install_path)安装数据和日活数据一览三种行为日志数据一览预处理数据

通过联结dau和install表,生成用户活跃日期和初次安装日期的时间间隔,便于我们筛选不同时间间隔的数据。

#联立dau和install表

login_interval = pd.merge(dau,install,on='user_id',how= 'left',suffixes=['','_install'])

#定义一个函数,返回时间间隔,利用apply,在整个df上运行

def time_interval(series):

end_date = datetime.strptime(series['log_date'],'%Y-%m-%d')

first_date = datetime.strptime(series['log_date_install'],'%Y-%m-%d')

interval = int((end_date-first_date).days)

return interval

login_interval['interval'] = login_interval.apply(time_interval,axis=1)

取出用户首次访问后第7-13天的数据,根据用户在第7-13天区间内登录天数/7,得到登录密度,作为模型的因变量

interval713 = login_interval[(login_interval.interval>=7)&(login_interval.interval<=13)]

ds713 = round(interval713.groupby('user_id')['interval'].count()/7,4)

ds713 = pd.DataFrame(ds713).reset_index()

#合并分析对象用户和登录密度数据

#选择安装日期在2013-06-01到2013-08-25的数据

install_713_ds = pd.merge(install[(install.log_date>='2013-06-01')&(install.log_date<='2013-08-25')],ds713,on='user_id',how='left')

install_713_ds.fillna(0,inplace=True)

install_713_ds.rename(columns={'interval':'density'},inplace=True)用作分析的用户的相关信息和第二周登陆密度数据

生成三类社交行为的每日次数数据、每日行为比率、和每日行为主成分数据。此处只展示战斗的处理过程,协作行为和发送信息的行为处理类似。

#生成关于战斗的数据

#合并战斗数据和首次访问数据

battle_install = pd.merge(battle,install,on='user_id',suffixes=['','_install'])

#计算战斗时间和首次访问时间差

battle_install['interval'] = battle_install.apply(time_interval,axis=1)

#取出时间差在一周内(0-6)天的数据

battle_install2 = battle_install[(battle_install.interval>=0)&(battle_install.interval<=6)]

#将0-6天内的战斗数据结构,以每天作为列,战斗次数作为值。

battle_install2 = battle_install2[['user_id','count','interval']]

battle_count_06 = battle_install2.pivot_table(index='user_id',columns='interval',

aggfunc='sum',fill_value=0).droplevel(0,axis=1).reset_index()

battle_count_06.rename(columns={0:'d0',1:'d1',2:'d2',3:'d3',4:'d4',5:'d5',6:'d6'},inplace=True)

#生成比率数据和PCA后数据

#比率即每日发生行为次数/7日行为总次数

battle_pct_06 = battle_count_06.iloc[:,1:]

battle_pct_06 = round(battle_pct_06.div(battle_pct_06.sum(axis=1),axis=0),3)

battle_pct_06['user_id'] = battle_count_06['user_id']

#输出主成分数据,减小变量间的相关性

from sklearn.decomposition import PCA

from sklearn.preprocessing import StandardScaler

battle_pca_06 = battle_count_06.iloc[:,1:]

pca_battle = PCA()

ss = StandardScaler()

battle_pca_06_2 = ss.fit_transform(battle_pca_06)

pca_battle.fit(battle_pca_06_2)

battle_pca_06_3 = pca_battle.transform(battle_pca_06_2)

battle_pca_06 = pd.DataFrame(battle_pca_06_3)

battle_pca_06['user_id'] = battle_count_06['user_id']

battle_pca_06.rename(columns={0:'PC1',1:'PC2',2:'PC3',3:'PC4',4:'PC5',5:'PC6',6:'PC7'},inplace=True)处理后的战斗行为数据一览

同样的方法处理协作行为数据、发送消息行为数据。社交行为的聚类分析

对battle,message,help的count,ratio,pca成分,分别进行3-6类的KMeans聚类(因为不确定聚几类最好,但通常分析选择3-6类),将类作为新的自变量。则共产生3*3*4=36个变量。

写一个函数,来循环聚类,这样只需要调用3次方法就可,不用反复聚类。

from sklearn.cluster import KMeans

# 用来生成关于类数据的函数

def behavior_cluster(x_count,x_ratio,x_pca):

df = pd.DataFrame()

user = x_count.iloc[:,0]

for i in np.arange(3,7,1):

km_count = KMeans(n_clusters=i,max_iter=500)

km_ratio = KMeans(n_clusters=i,max_iter=500)

km_pca = KMeans(n_clusters=i,max_iter=500)

x_count = x_count.iloc[:,1:]

x_ratio = x_ratio.iloc[:,:-1]

x_pca = x_pca.iloc[:,:-1]

count_class = km_count.fit_predict(x_count)

ratio_class = km_ratio.fit_predict(x_ratio)

pca_class = km_pca.fit_predict(x_pca)

count_class = pd.Series(count_class,name=f'count_class{i}_clusterid')

ratio_class = pd.Series(ratio_class,name=f'ratio_class{i}_clusterid')

pca_class =pd.Series(pca_class,name=f'pca_class{i}_clusterid')

df = pd.concat([df,count_class],axis=1)

df = pd.concat([df,ratio_class],axis=1)

df = pd.concat([df,pca_class],axis=1)

df = df.applymap(lambda x:x+1)

df['user_id'] = user

return df

battle_class = behavior_cluster(battle_count_06,battle_pct_06,battle_pca_06)

message_class = behavior_cluster(message_count_06,message_pct_06,message_pca_06)

help_class = behavior_cluster(help_count_06,help_pct_06,help_pca_06)聚类后的3类社交行为

我们将用户的登录密度和与“战斗”相关的类数据合并。与“发送消息”相关的类数据合并,与“协作”相关的类数据合并,用0替换“NA”(部分用户没有发生三类社交行为,这里用0类来代替,python的聚类输出的label是以0开始,我在上述的聚类方法里,将所有label加1后再输出,这里就可以用0类来指代无社交行为的用户)。

cluster_data = pd.merge(install_713_ds,battle_class,on='user_id',how='left')

cluster_data = pd.merge(cluster_data,message_class,on='user_id',how='left',

suffixes=['_battle',''])

cluster_data = pd.merge(cluster_data,help_class,on='user_id',how='left',

suffixes=['_message','_help'])

#将缺失行为聚类数据的,统一用0类填充

cluster_data.fillna(0,inplace=True)

再按照每类的登录密度,由小到大对每种聚类内部进行重新排列

cluster_data_melt = cluster_data.drop(columns=['log_date','install_time','gender'

,'generation','device_type'])

cluster_data_melt = cluster_data_melt.melt(id_vars=['user_id','density'])

cluster_data_avg = cluster_data_melt.groupby(['variable','value'])['density'].mean().reset_index().rename(columns = {'density':'avg_density'})

#按照【类别,均值】升序排列,每类里,根据均值生成新的升序排序号

cluster_data_avg.sort_values(by=['variable','avg_density'],inplace=True)

g_cluster = cluster_data_avg.groupby('variable')

cluster_data_avg['value2'] = g_cluster['value'].transform(lambda x:np.sort(x))

# 按照新的类编号进行合并,将每种行为聚类的均值,添加到用户表中

cluster_data_melt2 = pd.merge(cluster_data_melt,cluster_data_avg,on=['variable','value'])

cluster_data_melt2.head()按照平均密度对各聚类内部进行重新排序,value2为新的各类内部排序编号

再pivot上表,以value2(新的排序编号)作为值。产生的数据表作为自变量输入决策树模型中。

cluster_data2 = pd.pivot_table(data=cluster_data_melt2,index=['user_id','density'],

columns='variable',values='value2')

cluster_data2.reset_index(inplace=True)以社交行为的聚类结果作为自变量进行决策树分析,并可视化输出

from sklearn.tree import export_graphviz

from sklearn.tree import DecisionTreeClassifier

dtc = DecisionTreeClassifier()

X = cluster_data2.iloc[:,2:]

y =cluster_data2.iloc[:,1].astype('str')

dtc.fit(X=X,y=y)

dtc_tree = export_graphviz(dtc,out_file='yourpath/dtc_tree.dot',

feature_names=X.columns,class_names=np.unique(y.values),filled=True,

rounded=True,special_characters=True)可视化决策树

由可视化决策树结果,可以看到第一重要的是ratio_class4_clusterid_help,说明,用比率数据来分析协作行为的模式,对分析登陆密度最好。

那么,来查看下,类为4的协作的比率类的平均登录密度。

cluster_data3 = cluster_data_melt2[cluster_data_melt2.variable == 'ratio_class4_clusterid_help'][['user_id','avg_density','value2']]

cluster_data3.rename(columns={'value2':'cluster'},inplace=True)

sns.scatterplot(cluster_data3.cluster,cluster_data3.avg_density)协作行为比率聚4类的各类平均登录密度

可以看到,1,2类,在第2周的平均登录密度很低,只有0.2不到,平均只有1天。

第4类最好,登录密度在0.6左右,大概在4天左右。

接着我们来观察各个类中协作行为的比率随经过天数的变化情况

help_pct_06_class = pd.merge(help_pct_06,cluster_data3,on = 'user_id')

#计算4个类的协作行为比率随天数变化的均值

draw_help_pca_06 = help_pca_06_class.pivot_table(index='cluster').drop(

columns=['user_id','avg_density'])

draw_help_pct_06.T.plot()协作行为聚4类的各类比率每日变化

可以看到,第1类,第2类用户协作行为都集中在前2天,后续没有产生协作行为,最终第二周登录密度很低。

由数据结果看来,第一周的协作行为发生过多集中发生前2天的用户,第二周的登录密度都不高。而最好的第4类用户,协作行为在第4天有明显的增加。并且保持着持续的稳定发生。

所以考虑通过设计,来促进用户在第3、4天后的协作行为发生。

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐