zoukankan      html  css  js  c++  java
  • 零基础天池新闻推荐初学-02-数据分析

    01 数据分析作用和关注点

    主要作用:在于熟悉了解整个数据集的基本情况,包括每个文件里有哪些数据,具体每个文件中的每个字段表示什么实际含义,以及数据集中特征中之间的相似性;

    rs的数据分析的主要关注点:

    • 用户本身的基本属性
    • 文章基本属性
    • 用户和文章交互的一些分布
    • 召回策略的选择
    • 考虑特征工程方面做一下准备

    02 使用用pandas_profiling来做数据分析

    #%% 01 导包
    
    %matplotlib inline
    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")
    
    #%% 02 读取数据
    
    path = 'E:\阿里云开发者-天池比赛\06_天池新闻APP推荐\'
    save_path = 'E:\PycharmProjects\TianChiProject\00_山枫叶纷飞\competitions\006_dw_RecommandNews\'
    
    #####train
    # 训练集用户点击日志
    train_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
    # 测试集用户点击日志
    test_click = pd.read_csv(path+'testA_click_log.csv')
    
    #####合并 (数据格式一致)
    tt_click = pd.concat([train_click, test_click], axis=0)
    
    #%% 03 数据预处理
    dfs = [train_click, test_click, tt_click]
    names = ['train_click', 'test_click', 'tt_click']
    # 3.1 计算用户点击的时间戳进行逆序排序
    # for df in dfs:
    #     df['rank'] = df.groupby(['user_id'])['click_timestamp'].rank(ascending=False).astype(int)
    
    # 3.2 计算用户点击文章的次数, 并添加新的一列count
    # for df, name in zip(dfs, names):
    #     df['count'] = df.groupby(['user_id'])['click_timestamp'].transform('count')
    
    #%% 04 用pandas_profiling生成三分数据报告
    import pandas_profiling
    for df, name in zip(dfs, names):
        df = df.merge(item_df, how='left', on=['click_article_id'])
        pfr = pandas_profiling.ProfileReport(df)
        pfr.to_file(save_path + "profiling\{}_pandas_profiling.html".format(name))
    

    03 数据浏览(以train+test合并后数据为例,train和test的数据格式基本一致)

    -1. 由分别的Profiling Report可以得出:训练集的用户ID由0 ~ 199999,而测试集A的用户ID由200000 ~ 249999。

    1. 总数据行数为163K
    2. user_id 总数为250K,训练集200K,测试集50K
    3. 点击时间click_timestamp ,分布均匀,几乎没有重复值 (受pandas-profiling的分桶bin影响看着有些起伏)
    4. 点击环境click_environment
      从点击环境click_environment来看,仅有2499 次(占0.2%)点击环境为1;仅有38948次(占2.4%)点击环境为2;剩余(占97.5%)点击环境为4。
    5. 点击设备组click_deviceGroup
      可以看出设备1和设备3的占比分别为62.2%和34.2%。

    04 用pandas_profiling生成三份数据报告

    import pandas_profiling
    for df, name in zip(dfs, names):
        df = df.merge(item_df, how='left', on=['click_article_id'])
        pfr = pandas_profiling.ProfileReport(df)
        pfr.to_file(save_path + "profiling\{}_pandas_profiling.html".format(name))
    

    05 数据分析(以train+test合并后数据为例,train和test的数据格式基本一致)

    为后续构建新的特征做准备。

    5.1 用户重复点击

    user_click_count = tt_click.groupby(['user_id', 'click_article_id'])['click_timestamp'].agg({'count'}).reset_index()
    # print(user_click_count)
    user_click_count.sort_values(by='count', inplace=True)
    print('打印前10个和后10个:')
    print(user_click_count[:10])
    print(user_click_count[-10:])
    
    #%% 5.1.2 分析重复的数量类型
    
    user_click_count['count'].unique()
    
    #%% 5.1.3 用户点击新闻次数分布
    
    user_click_count.loc[:,'count'].value_counts()
    """
    可以看出:有1605541(约占99.2%)的用户未重复阅读过文章,仅有极少数用户重复点击过某篇文章。 
    这个也可以单独制作成特征.
    """
    

    5.2 用户点击环境变化分析

    这个看着没啥意义,跳过

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

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

    5.4 取前50看看

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

    5.5 由上上面的图得出, 点击次数排名在25000之后.点击次数就变得特别低,具体分析; 可以看出点击次数小于等于两次的用户非常的多,这些用户可以认为是非活跃用户

    plt.plot(user_click_item_count[25000:])
    

    5.6 新闻点击次数分析:新闻的冷热门分类

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

    5.6.2 取热门新闻前100看看

    plt.plot(item_click_count[:100])
    """
    可以看出点击次数最多的前100篇新闻,点击次数大于1000次;
    点击次数最多的前20篇新闻,点击次数大于2500。思路:可以定义这些新闻为热门新闻, 这个也是简单的处理方式,后面我们也是根据点击次数和时间进行文章热度的一个划分。
    """
    

    5.6.3 取冷门新闻热度排名3000以后的新闻看看

    plt.plot(item_click_count[3000:])
    """
    可以发现很多新闻只被点击过几次。
    思路:可以定义这些新闻是冷门新闻。
    """
    

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

    tmp = tt_click.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()
    

    tmp.sort_values('排序一下,发现shift是反转传播方向')

    5.7.2 新闻共现频次 画个图 直观地看一看

    x = union_item['click_article_id']
    y = union_item['count']
    plt.scatter(x, y)
    

    5.7.3 至少共现一次的统计

    plt.plot(union_item['count'].values[40000:])
    """
    由图可知:大概有70000+个pair至少共现一次。
    """
    

    5.8 新闻文章类型的分类信息

    #不同类型的新闻出现的次数
    print(tt_click.columns)
    plt.plot(tt_click['category_id'].value_counts().values)
    
    #%% 5.9. 用户点击的新闻类型的偏好(兴趣的广泛程度)
    tt_click.groupby('user_id')['category_id'].nunique().reset_index().describe()
    plt.plot(sorted(tt_click.groupby('user_id')['category_id'].nunique(), reverse=True))
    """
    从上图中可以看出有一小部分用户阅读类型是极其广泛的,大部分人都处在20个新闻类型以下。
    """
    

    5.10. 用户查看文章的长度的分布

    """
    通过统计不同用户点击新闻的平均字数,这个可以反映用户是对长文更感兴趣还是对短文更感兴趣。
    结论:
    从上图中可以发现有一小部分人看的文章平均词数非常高,也有一小部分人看的平均文章次数非常低。
    
    大多数人偏好于阅读字数在200-400字之间的新闻。
    
    """
    plt.plot(sorted(tt_click.groupby('user_id')['words_count'].mean(), reverse=True) )
    #挑出大多数人的区间仔细看看
    plt.plot(sorted(tt_click.groupby('user_id')['words_count'].mean(), reverse=True)[1000:45000])
    

    5.11. 用户点击新闻的时间分析

    #为了更好的可视化,这里把时间进行归一化操作
    from sklearn.preprocessing import MinMaxScaler
    mm = MinMaxScaler()
    tt_click['click_timestamp'] = mm.fit_transform(tt_click[['click_timestamp']])
    tt_click['created_at_ts'] = mm.fit_transform(tt_click[['created_at_ts']])
    
    user_click_merge = tt_click.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()
        ```
    # 点击时间差的平均值
    ``` python
    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))
    

    06 总结 (复制粘贴)

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

    1. 训练集和测试集的用户id没有重复,也就是测试集里面的用户没有模型是没有见过的
    2. 训练集中用户最少的点击文章数是2, 而测试集里面用户最少的点击文章数是1
    3. 用户对于文章存在重复点击的情况, 但这个都存在于训练集里面
    4. 同一用户的点击环境存在不唯一的情况,后面做这部分特征的时候可以采用统计特征 (这点在自己尝试做分析的时候没有考虑到,给忽略了)
    5. 用户点击文章的次数有很大的区分度,后面可以根据这个制作衡量用户活跃度的特征
    6. 文章被用户点击的次数也有很大的区分度,后面可以根据这个制作衡量文章热度的特征
    7. 用户看的新闻,相关性是比较强的,所以往往我们判断用户是否对某篇文章感兴趣的时候, 在很大程度上会和他历史点击过的文章有关
    8. 用户点击的文章字数有比较大的区别, 这个可以反映用户对于文章字数的区别
    9. 用户点击过的文章主题也有很大的区别, 这个可以反映用户的主题偏好
    10. 不同用户点击文章的时间差也会有所区别, 这个可以反映用户对于文章时效性的偏好

    所以根据上面的一些分析,可以更好的帮助我们后面做好特征工程, 充分挖掘数据的隐含信息。

    07 pandas语法复习笔记

    • apply(),会将待处理的对象拆分成多个片段,然后对各片段调用传入的函数,最后尝试将各片段组合到一起。
    • transform(),形变、改变,会将一个函数应用到各个分组;举例count()会聚合对应的分组,transform('count')会把分组后的函数应用到每一行数据上——保持总数据行数不变。
    • agg,pandas的数据聚合方法,可以对一列或者多列使用函数,将一个函数使用在一个数列上,然后返回一个标量的值。内置函数名需要用引号。

    08 引用链接

  • 相关阅读:
    739. Daily Temperatures
    556. Next Greater Element III
    1078. Occurrences After Bigram
    1053. Previous Permutation With One Swap
    565. Array Nesting
    1052. Grumpy Bookstore Owner
    1051. Height Checker
    数据库入门及SQL基本语法
    ISCSI的概念
    配置一个IP SAN 存储服务器
  • 原文地址:https://www.cnblogs.com/zhazhaacmer/p/14064135.html
Copyright © 2011-2022 走看看