内容导航:
- 零基础入门推荐系统 - 新闻推荐 - 实操2
- 比赛数据分析:
- 用户属性分析:
- 训练集和测试集中分别有多少用户?
- 用户城市分布有什么规律?
- 平均每个用户会点击多少个文章?
- 点击来源与文章点击次数是否存在关联?
- 用户行为分析:
零基础入门推荐系统 - 新闻推荐 - 实操2
比赛数据分析:
用户属性分析:
训练集和测试集中分别有多少用户?
def count_user_number(data):
number = len(data.user_id.unique())
return number
print(count_user_number(train_clicks))
print(count_user_number(test_clicks))
- 小结:
可以看出训练集中共有200000个用户, 测试集中共有50000个用户.
用户城市分布有什么规律?
对训练集和测试集分别对用户的城市进行柱形图绘制, 查看其特点.
test_clicks.groupby('click_country')['user_id'].nunique().sort_values(ascending=False)
发现测试集中用户主要都是城市1的. 因为数据差距太大, 我们把城市1的数据去除, 看一下其余城市的分布情况, 对齐进行可视化操作.
test_clicks.groupby('click_country')['user_id'].nunique().sort_values(ascending=False)[1:].plot(kind='bar')
plt.show()
同时, 看一下训练集的用户的城市分布情况:
train_clicks.groupby('click_country')['user_id'].nunique().sort_values(ascending=False)
同样的, 发现训练集和测试集用户的城市整体的分布差不多, 而且都是城市1的用户的数量远远大于其他城市用户的数量.
我们接下来看一下, 把城市1的数据去除, 看一下训练集其余城市的分布情况.
train_clicks.groupby('click_country')['user_id'].nunique().sort_values(ascending=False)[1:].plot(kind='bar')
plt.show()
- 小结:
可以看出整体数据集的用户的城市主要分布在城市1, 城市10和城市11.
平均每个用户会点击多少个文章?
整体来看的话,
# 计算训练集中点击文章不重复数
train_article_click_num = len(train_clicks.click_article_id.unique())
# 计算训练集中用户数
train_user_num = len(train_clicks.user_id.unique())
# 计算训练集中平均每个用户会点击多少个文章
train_avg_article_per_user = train_article_click_num / train_user_num
train_avg_article_per_user
可以得到 0.15558
的结果. 也就是说, 大多数用户点击文章偏少.
我们再来进一步看一下点击不同数量文章的用户数:
train_df = pd.DataFrame(train_clicks.groupby('user_id')['click_article_id'].nunique().reset_index())
train_df.groupby('click_article_id')['user_id'].nunique().sort_index()
train_df.groupby('click_article_id')['user_id'].nunique().sort_index().plot(kind='line')
因为整体用户点击数量超过50, 就基本是极少数用户了, 我们可以进一步分析一下大众用户的一个点击文章的一个分布.
train_df2 = pd.DataFrame(train_df.groupby('click_article_id')['user_id'].nunique().sort_index().head(50).reset_index())
plt.bar(train_df2.click_article_id, train_df2.user_id)
plt.show()
将上面关于该部分的代码进行函数封装, 相关函数如下:
# 编写计算每个用户平均点击文章数(绝对数)的函数
def avg_article_num_per_user(data):
# 计算数据集中点击文章不重复数
article_click_num = len(data.click_article_id.unique())
# 计算数据集中用户数
user_num = len(data.user_id.unique())
# 计算数据集中平均每个用户会点击多少个文章
avg_article_per_user = article_click_num / user_num
return avg_article_per_user
avg_article_num_per_user(train_clicks)
avg_article_num_per_user(test_clicks)
def plt_user_article_num(data):
df = pd.DataFrame(data.groupby('user_id')['click_article_id'].nunique().reset_index())
print(df)
plt.subplot(211)
df.groupby('click_article_id')['user_id'].nunique().sort_index().plot(kind='line')
plt.show()
df2 = pd.DataFrame(df.groupby('click_article_id')['user_id'].nunique().sort_index().head(50).reset_index())
plt.subplot(212)
plt.bar(df2.click_article_id, df2.user_id)
plt.show()
plt_user_article_num(test_clicks)
测试集绘制如下:
可以看出大部分用户点击文章数量处于2~10
之间. 所以, 如何精准的给用户推送这相对精准的新闻也是事关重要的.
对于测试集来看, 整体用户点击文章数量分布一致, 但是测试集存在一部分大量的用户仅仅点击文章数量为1
. 这也相对于训练集来说, 两者的不同.
综上来说, 数据集中大部分用户点击文章数量处于1~10
之间. 训练集中用户最少的点击文章数是2, 而测试集里面用户最少的点击文章数是1.
点击来源与文章点击次数是否存在关联?
df = train_clicks.groupby('click_referrer_type')['click_article_id'].nunique().sort_index().reset_index()
print(df)
plt.bar(df.click_referrer_type, df.click_article_id)
df = test_clicks.groupby('click_referrer_type')['click_article_id'].nunique().sort_index().reset_index()
print(df)
plt.bar(df.click_referrer_type, df.click_article_id)
- 小结
可以看出数据集中, 点击来源与文章点击次数存在一定的关系, 而且点击来源1, 点击来源2, 和点击来源5这三类文章点击次数是最多的, 用户点击文章次数也是最多的. 所以, 这三类的来源是用户着重关注的.
用户行为分析:
#为了更好的可视化,这里把时间进行归一化操作
from sklearn.preprocessing import MinMaxScaler
mm = MinMaxScaler()
user_click_merge['click_timestamp'] = mm.fit_transform(user_click_merge[['click_timestamp']])
user_click_merge['created_at_ts'] = mm.fit_transform(user_click_merge[['created_at_ts']])
user_click_merge = user_click_merge.sort_values('click_timestamp')
def mean_diff_time_func(df, col):
df = pd.DataFrame(df, columns={col})
df['time_shift1'] = df[col].shift(1).fillna(0)
df['diff_time'] = abs(df[col] - df['time_shift1'])
return df['diff_time'].mean()
# 点击时间差的平均值
mean_diff_click_time = user_click_merge.groupby('user_id')['click_timestamp', 'created_at_ts'].apply(lambda x: mean_diff_time_func(x, 'click_timestamp'))
plt.plot(sorted(mean_diff_click_time.values, reverse=True))