Datawhale 实践项目 天池赛中零基础入门推荐系统 Task02:数据分析 笔记[让我看看]

[让我看看谁那么帅]

1.数据分析

数据分析的价值主要在于熟悉了解整个数据集的基本情况包括每个文件里有哪些数据,具体的文件中的每个字段表示什么实际含义,以及数据集中特征之间的相关性,在推荐场景下主要就是分析用户本身的基本属性,文章基本属性,以及用户和文章交互的一些分布,这些都有利于后面的召回策略的选择,以及特征工程。

1.1导包

import pandas as pd
import numpy as np

import matplotlib.pyplot as plt
import seaborn as sns
plt.rc('font',family = 'SimHei',size = 13)

import os,gc,re,warnings,sys
warnings.filterwarnings("ignore")

plt.rcParams的用法超链接
上面用的plt.rc()来设置的,但是好像没有搜到相关用法[害]

1.2 读取数据

path = './data/'

trn_click = pd.read_csv(path+'train_click_log.csv')
item_df = pd.read_csv(path+'articles.csv')
item_df = item_df.rename(columns = {'article_id':'click_article_id'})
# 命名,方便后面的match计算
item_emb_df = pd.read_csv(path+'articles_emb.csv')

#test
tst_click = pd.read_csv(path+'testA_click_log.csv')

.rename() 可以用来更改Dataframe的索引名

1.3数据预处理

计算用户点击rank和点击次数

# 对每个用户的点击时间戳进行排序
trn_click['rank'] = trn_click.groupby(['user_id'])['click_timestamp'].rank(ascending = False).astype(int)
tst_click['rank'] = tst_click.groupby(['user_id'])['click_timestamp'].rank(ascending = False).astype(int)

Datafame.rank()的迷之用法
1、默认情况下,rank是通过“为各组分配一个平均排名”的方式破坏平级关系的
莫名其妙的排序用法,例如一Series数组中 obj = pd.Series([7,-5,7,4,2,0,4])
按道理第1个7和第3个7在其obj进行排序时,它们相等,而且位置在第6,7,所以他们的排名就都是6.5了
在这里插入图片描述astype()是将其转化为什么类型,像astype(int),转化为int类型,6.5应该就变成了6
在这里插入图片描述

#计算用户点击文章的次数,并添加新的一列count
trn_click['click_cnts'] = trn_click.groupby(['user_id'])['click_timestamp'].transform('count')
tst_click['click_cnts'] = tst_click.groupby(['user_id'])['click_timestamp'].transform('count')

将训练集用户点击日和测试集用户点击日志按’user_id’进行分组计算’click_timestamp’,并通过transform()进行统计文章次数,像如果用户01 初次了3次,就记录为3次,而csv表格中每一行数据就是用户点击一篇文章的日志信息,所以这样就可以统计计算出用户点击文章的次数,用小小的例子体会一下下
创建一个对象
在这里插入图片描述groupby后
在这里插入图片描述

然后用transform方法
在这里插入图片描述

1.4 数据浏览

1.4.1 用户点击日志文件_训练集

trn_click = trn_click.merge(item_df,how = 'left',on=['click_article_id'])

merge的方法使用 点我就知道了
连接前trn_click
在这里插入图片描述在这里插入图片描述连接后的
在这里插入图片描述train_click_log.csv文件数据中每个字段的含义

  1. user_id: 用户的唯一标识
  2. click_article_id: 用户点击的文章唯一标识
  3. click_timestamp: 用户点击文章时的时间戳
  4. click_environment: 用户点击文章的环境
  5. click_deviceGroup: 用户点击文章的设备组
  6. click_os: 用户点击文章时的操作系统
  7. click_country: 用户点击文章时的所在的国家
  8. click_region: 用户点击文章时所在的区域
  9. click_referrer_type: 用户点击文章时,文章的来源
# 用户点击日志信息
trn_click.info()

在这里插入图片描述

trn_click.describe()

在这里插入图片描述

#训练集中的用户数量差不多为20w
trn_click.user_id.nunique()

在这里插入图片描述

trn_click.groupby('user_id')['click_article_id'].count().min()

在这里插入图片描述

1.4.2 画直方图看一下基本的属性分布

plt.figure()
plt.figure(figsize=(15,20))
plt.figure()
plt.figure(figsize=(15, 20))
i = 1
for col in ['click_article_id', 'click_timestamp', 'click_environment', 'click_deviceGroup', 'click_os', 'click_country', 
            'click_region', 'click_referrer_type', 'rank', 'click_cnts']:
    plot_envs = plt.subplot(5, 2, i)
    i += 1
    v = trn_click[col].value_counts().reset_index()[:10]
    fig = sns.barplot(x=v['index'], y=v[col])
    for item in fig.get_xticklabels():
        item.set_rotation(90)
    plt.title(col)
plt.tight_layout()
plt.show()

reset_index()函数的用法
(1) get_xticklabels() 应该是可以获取那个标签然后在下面更改
(2)plt.tight_layout()的用法

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

思考 对于数据框中不同维度的数据的探索可以对每一维度的数据进行画图可视化`来展示

从点击时间clik_timestamp来看,分布较为平均,可不做特殊处理。由于时间戳是13位的,后续将时
间格式转换成10位方便计算。
从点击环境click_environment来看,仅有1922次(占0.1%)点击环境为1;仅有24617次(占2.3%)
点击环境为2;剩余(占97.6%)点击环境为4。
从点击设备组click_deviceGroup来看,设备1占大部分(60.4%),设备3占36%。

1.4.3 测试集用户点击日志

tst_click = tst_click.merge(item_df,how='left',on=['click_article_id'])
tst_click.head()

在这里插入图片描述

tst_click.describe()

在这里插入图片描述
我们可以看出训练集和测试集的用户是完全不一样的 训练集的用户ID由0199999,而测试集A的用户ID由200000249999

在这里插入图片描述

1.4.4 新闻文章信息数据表

#新闻文章数据集浏览
item_df.head().append(item_df.tail())

在这里插入图片描述

item_df['words_count'].value_counts()

在这里插入图片描述

print(item_df['category_id'].nunique()) # 461个文章主题 
item_df['category_id'].hist()

在这里插入图片描述
在这里插入图片描述

1.4.5 新闻文章embedding向量表示

在这里插入图片描述
在这里插入图片描述

1.4.6 数据分析

用户重复点击

user_click_merge = trn_click.append(tst_click)
# 用户重复点击
user_click_count = user_click_merge.groupby(['user_id','click_article_id'])\
                  ['click_timestamp'].agg({'count'}).reset_index()

**reset_index()**重整索引 用reset_index()后

在这里插入图片描述在这里插入图片描述
在这里插入图片描述在这里插入图片描述

user_click_count[:10]
user_click_count[user_click_count['count']>7]

在这里插入图片描述

# 用户点击新闻次数
user_click_count.loc[:,'count'].value_counts()

在这里插入图片描述
可以看出:有1605541(约占99.2%)的用户未重复阅读过文章,仅有极少数用户重复点击过某篇文
章。 这个也可以单独制作成特征

1.4.7 用户点击环境变化分析

def plot_envs(df,cols,r,c):
    plt.figure()
    plt.figure(figsize = (10,5))
    i = 1
    for col in cols:
        plt.subplot(r,c,i)
        i += 1
        v = df[col].value_counts().reset_index()
        fig = sns.barplot(x=v['index'],y=v[col])
        for item in fig.get_xticklabels():
            item.set_rotation(90)
        plt.title(col)
    plt.tight_layout()
    plt.show()
sample_user_ids = np.random.choice(tst_click['user_id'].unique(),size=5,replace=False)
sample_users = user_click_merge[user_click_merge['user_id'].isin(sample_user_ids)]
cols = ['click_environment','click_deviceGroup','click_os','click_country',\
        'click_region','click_referrer_type']
for _,user_df in sample_users.groupby('user_id'):
    plot_envs(user_df,cols,2,3)

isin()接受一个列表,判断该列中元素是否在列表中。

在这里插入图片描述可以看出绝大多数数的用户的点击环境是比较固定的。思路:可以基于这些环境的统计特征来代表该用
户本身的属性

1.4.8 用户点击新闻数量的分布

user_click_item_count = sorted(user_click_merge.groupby('user_id')['click_article_id'].count(),reverse=True)
plt.plot(user_click_item_count)

在这里插入图片描述

1.4.9 可以根据用户的点击文章次数看出用户的活跃度

。
点击次数排前50的用户的点击次数都在100次以上。思路:我们可以定义点击次数大于等于100次的用户为活跃用户,这是一种简单的处理思路, 判断用户活跃度,更加全面的是再结合上点击时间,后面我们会基于点击次数和点击时间两个方面来判断用户活跃度

#点击次数排名在[25000:50000]之间 
plt.plot(user_click_item_count[25000:50000])

可以看出点击次数小于等于两次的用户非常的多,这些用户可以认为是非活跃用户

1.4.10新闻点击次数分析

item_click_count = sorted(user_click_merge.groupby('click_article_id')['user_id'].count(),reverse=True)

在这里插入图片描述

plt.plot(item_click_count[:100])

可以看出点击次数最多的前100篇新闻,点击次数大于1000次

plt.plot(item_click_count[:20])

点击次数最多的前20篇新闻,点击次数大于2500。思路:可以定义这些新闻为热门新闻, 这个也是简 单的处理方式,后面我们也是根据点击次数和时间进行文章热度的一个划分。

plt.plot(item_click_count[3500:])

可以发现很多新闻只被点击过一两次。思路:可以定义这些新闻是冷门新闻。

1.4.11 新闻共现频次:两篇新闻连续出现的次数

tmp = user_click_merge.sort_values('click_timestamp')
tmp['next_item'] = tmp.groupby(['user_id'])['click_article_id'].transform(lambda x:x.shift(-1))
union_item = tmp.groupby(['click_article_id','next_item'])['click_timestamp'].agg({'count'}).reset_index().sort_values('count', ascending=False)
union_item[['count']].describe()

在这里插入图片描述

# 画个图直观地看一看
x = union_item['click_article_id']
y = union_item['count']
plt.scatter(x.y)
plt.plot(union_item['count'].values[40000:])

大概有70000个pair至少共现一次

1.4.12新闻文章信息

#不同类型的新闻出现的次数
plt.plot(user_click_merge['category_id'].value_counts().values)

在这里插入图片描述

#出现次数比较少的新闻类型, 有些新闻类型,基本上就出现过几次
plt.plot(user_click_merge['category_id'].value_counts().values[150:])

在这里插入图片描述

#新闻字数的描述性统计
user_click_merge['words_count'].describe()

在这里插入图片描述

plt.plot(user_click_merge['words_count'].values)

在这里插入图片描述

1.4.13用户点击的新闻类型的偏好

此特征可以用于度量用户的兴趣是否广泛。

plt.plot(sorted(user_click_merge.groupby('user_id')['category_id'].nunique(), reverse=True))

从上图中可以看出有一小部分用户阅读类型是极其广泛的,大部分人都处在20个新闻类型以下。

user_click_merge.groupby('user_id')['category_id'].nunique().reset_index().describe()

在这里插入图片描述

1.4.14用户查看文章的长度的分布

通过统计不同用户点击新闻的平均字数,这个可以反映用户是对长文更感兴趣还是对短文更感兴趣。

plt.plot(sorted(user_click_merge.groupby('user_id')['words_count'].mean(),reverse=True))

在这里插入图片描述
从上图中可以发现有一小部分人看的文章平均词数非常高,也有一小部分人看的平均文章次数非常低。

大多数人偏好于阅读字数在200-400之间的新闻

# 挑出大多数人的区间仔细看看
plt.plot(sorted(user_click_merge.groupby('user_id')['words_count'].mean(),reverse=True)[1000:45000])

在这里插入图片描述
可以发现大多数人都是看250字以下的文章

#更加详细的参数
user_click_merge.groupby('user_id')['words_count'].mean().reset_index().describe()

在这里插入图片描述

1.4.15用户点击新闻的时间分析

#为了更好的可视化,这里把时间进行归一化操作
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')

user_click_merge.head()

在这里插入图片描述

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_created_time = user_click_merge.groupby('user_id')['click_timestamp', 'created_at_ts'].apply(lambda x: mean_diff_time_func(x, 'created_at_ts'))

plt.plot(sorted(mean_diff_created_time.values, reverse=True))

在这里插入图片描述
从图中可以发现用户先后点击文章,文章的创建时间也是有差异的

# 用户前后点击文章的相似性分布
item_idx_2_rawid_dict = dict(zip(item_emb_df['article_id'], item_emb_df.index))
del item_emb_df['article_id']
item_emb_np = np.ascontiguousarray(item_emb_df.values, dtype=np.float32)
# 随机选择5个用户,查看这些用户前后查看文章的相似性
sub_user_ids = np.random.choice(user_click_merge.user_id.unique(), size=15, replace=False)
sub_user_info = user_click_merge[user_click_merge['user_id'].isin(sub_user_ids)]

sub_user_info.head()

在这里插入图片描述

def get_item_sim_list(df):
    sim_list = []
    item_list = df['click_article_id'].values
    for i in range(0, len(item_list)-1):
        emb1 = item_emb_np[item_idx_2_rawid_dict[item_list[i]]]
        emb2 = item_emb_np[item_idx_2_rawid_dict[item_list[i+1]]]
        sim_list.append(np.dot(emb1,emb2)/(np.linalg.norm(emb1)*(np.linalg.norm(emb2))))
    sim_list.append(0)
    return sim_list
    for _, user_df in sub_user_info.groupby('user_id'):
    item_sim_list = get_item_sim_list(user_df)
    plt.plot(item_sim_list)

在这里插入图片描述
从图中可以看出有些用户前后看的商品的相似度波动比较大,有些波动比较小,也是有一定的区分度的

总结自己还是太菜了,学不过来,特征太多了感觉,很多东西写到后面就忘了前面定义的了

粘贴大佬的总结督促自己

总结
通过数据分析的过程, 我们目前可以得到以下几点重要的信息, 这个对于我们进行后面的特征制作和分析非常有帮助:

训练集和测试集的用户id没有重复,也就是测试集里面的用户没有模型是没有见过的
训练集中用户最少的点击文章数是2, 而测试集里面用户最少的点击文章数是1
用户对于文章存在重复点击的情况, 但这个都存在于训练集里面
同一用户的点击环境存在不唯一的情况,后面做这部分特征的时候可以采用统计特征
用户点击文章的次数有很大的区分度,后面可以根据这个制作衡量用户活跃度的特征
文章被用户点击的次数也有很大的区分度,后面可以根据这个制作衡量文章热度的特征
用户看的新闻,相关性是比较强的,所以往往我们判断用户是否对某篇文章感兴趣的时候, 在很大程度上会和他历史点击过的文章有关
用户点击的文章字数有比较大的区别, 这个可以反映用户对于文章字数的区别
用户点击过的文章主题也有很大的区别, 这个可以反映用户的主题偏好 10.不同用户点击文章的时间差也会有所区别, 这个可以反映用户对于文章时效性的偏好
所以根据上面的一些分析,可以更好的帮助我们后面做好特征工程, 充分挖掘数据的隐含信息。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

数据闲逛人

谢谢大嘎喔~ 开心就好

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值