1、前言
1.1项目背景
- 在这个流量越来越贵的时代,渠道方常常面临一个问题:拿到CP给的游戏之后该如何投放游戏,除了根据产品和运营人员定义的品类标签定向投放之外,还有没有其他更精准利用流量的方式进行投放?
- 大部分时候,我们拿到游戏后会有2-3天的冷启动测试阶段,那冷启动测试阶段的用户行为数据如何作为依据为后续投放做数据支撑?
1.2分析目标
- 假设喜欢A游戏的用户,大概率也喜欢B游戏,那么我们就可以针对玩过A游戏的这部分用户群体定向投放B游戏。我们需要根据历史用户行为数据计算所有游戏受用户喜欢的相关性,然后根据相关性锁定游戏投放的目标群体定向投放。
1.3分析思路
- 评估用户对游戏的喜爱程度
- 计算用户同时喜欢两种游戏的用户数
- 两两游戏组合按照用户数高低排序,用户数较高的游戏组合即表示该组游戏受用户喜欢相关性较高
- 计算相关性矩阵得到所有游戏的相关性图谱
1.4分析模型
本次分析共涉及两种模型,矩阵模型和相似度计算模型
矩阵模型:
X轴和Y轴分别表示用户玩游戏的单次时长和玩游戏的频次,我们定义用户喜欢该游戏的标准为同时满足下面两个条件:
- 玩该游戏的单次时长大于该游戏的平均时长
- 玩游戏频次大于该游戏所有用户的平均频次
相似度计算模型:
这里应用到基于物品的协同过滤算法,两个物品产生相似度是因为它们共同被很多用户喜欢,也就是说每个用户都可以通过他们的历史兴趣列表给物品“贡献”相似度,相似度计算包含两步:
- 计算两两组合的物品被用户喜欢的频次矩阵C
- 对C矩阵做归一化处理,得到余弦相似度矩阵W,矩阵里的值在0-1范围,越靠近1表示该组合物品越相似
说明:N(i)表示喜欢i物品的用户人数,分子表示同时喜欢物品i和物品j的用户数
2、理解数据
2.1数据集
该数据来源于某渠道2020/09/18-2020/09/20三天的用户行为数据,已去除敏感字段,共包含10万多条用户行为,数据集地址:密码:fiun
2.2字段含义
该数据共包含4个字段:
- user_id:用户ID
- game_id:游戏ID
- time_long:用户单次玩游戏时长(单位:分钟)
- timestamp:用户玩游戏时间戳
3、数据清洗和预处理
# 引入第三方库
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import math
import seaborn as sns
# 读取数据,并设置字段名称
data_user = pd.read_csv('user_game_data.csv',names=["user_id","game_id","time_long","timestamp"])
#探寻数据
data_user.head()
user_id | game_id | time_long | timestamp | |
---|---|---|---|---|
0 | 1 | 1 | 12 | 2020/9/18 21:17 |
1 | 5 | 19 | 12 | 2020/9/20 10:14 |
2 | 7 | 21 | 14 | 2020/9/18 19:17 |
3 | 15 | 7 | 8 | 2020/9/20 16:35 |
4 | 17 | 20 | 14 | 2020/9/19 5:06 |
# 查看数据基本信息
data_user.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 100836 entries, 0 to 100835
Data columns (total 4 columns):
user_id 100836 non-null int64
game_id 100836 non-null int64
time_long 100836 non-null int64
timestamp 100836 non-null object
dtypes: int64(3), object(1)
memory usage: 3.1+ MB
说明:该数据共包含100836条数据,各项字段数据完整,无缺失值处理
# 查看time_long(玩游戏单次时长)有无异常值
data_user["time_long"].describe()
count 100836.000000
mean 10.670267
std 4.521110
min 0.000000
25% 9.000000
50% 11.000000
75% 12.000000
max 980.000000
Name: time_long, dtype: float64
说明:time_long最大值是980分钟,数据异常
# 处理异常值:time_long(用户玩游戏单次时长正常范围是0-100分钟,超过100分钟的用平均值代替)
data_user['time_long']=data_user['time_long'].apply(lambda x:data_user["time_long"].mean() if x>100 else x)
# 查看处理后的time_long分布
data_user["time_long"].describe()
count 100836.000000
mean 10.654634
std 3.114415
min 0.000000
25% 9.000000
50% 11.000000
75% 12.000000
max 15.000000
Name: time_long, dtype: float64
# 查看有无异常用户(用户一天平均每天玩游戏次数大于100次默认为该用户刷机)
game_count=data_user.groupby(["user_id","game_id"])["time_long"].apply(lambda x : math.ceil(x.count()/3)).sort_values(ascending=False)
game_count.head(10)
user_id game_id
414 12 36
599 11 35
414 10 35
474 11 32
599 12 31
414 11 31
3 30
27 30
474 5 28
599 29 28
Name: time_long, dtype: int64
说明:用户无刷机行为,无异常数据处理
4、数据分析和可视化
# 求用户对游戏的喜爱程度,用户喜欢该游戏需同时满足:1、时长大于该游戏时长均值;2、频次大于该游戏频次均值
#求每个游戏的单次平均时长,和单天玩游戏的平均频次
game_mean=data_user.groupby("game_id").aggregate({
"time_long":