美文网首页
清洗与分析数据Dog_rates

清洗与分析数据Dog_rates

作者: RossH | 来源:发表于2019-04-18 23:16 被阅读0次

    简介

    本文将要整理 (以及分析和可视化) 的数据集是推特用户 @dog_rates 的档案, 推特昵称为 WeRateDogs。WeRateDogs 是一个推特主,他以诙谐幽默的方式对人们的宠物狗评分。这些评分通常以 10 作为分母。但是分子则一般大于 10:11/10、12/10、13/10 等等。为什么会有这样的评分?因为 "They're good dogs Brent." WeRateDogs 拥有四百多万关注者,曾受到国际媒体的报道。

    收集

    获取WeRateDogs Twitter数据集

    # WeRateDogs Twitter archive Dataframe
    twitter_archive = pd.read_csv('twitter-archive-enhanced.csv')
    

    下载并读取图像预测结果数据集

    # Download image-predictions.tsv
    url = "https://raw.githubusercontent.com/udacity/new-dand-advanced-china/master/%E6%95%B0%E6%8D%AE%E6%B8%85%E6%B4%97/WeRateDogs%E9%A1%B9%E7%9B%AE/image-predictions.tsv"
    urlretrieve(url, 'image-predictions.tsv')
    
    # image predictions Dataframe
    image_predict = pd.read_csv('image-predictions.tsv', sep='\t')
    

    获取转发数等额外数据

    # Twitter extra data
    extra_list = []
    with open('tweet_json.txt', 'r') as file:
        for line in file.readlines():
            jsonObj = json.loads(line)
            extra_list.append({'tweet_id': jsonObj['id'], 'retweet_count': jsonObj['retweet_count'], 'favorite_count':jsonObj['favorite_count']})
    extra_data = pd.DataFrame(extra_list)
    

    评估

    观察评估

    随机抽取5条推特样本数据观察

    twitter_archive.sample(5)
    

    各列数据含义

    列名 含义
    tweet_id 档案中的推特 ID
    in_reply_to_status_id 回复ID
    in_reply_to_user_id 被回复推文原始用户ID
    timestamp 发文时间
    source 消息来源(使用设备)
    text 推文内容
    retweeted_status_id 转发ID
    retweeted_status_user_id 转发用户ID
    retweeted_status_timestamp 转发时间
    expanded_urls 推文链接
    rating_numerator 评分分子
    rating_denominator 评分分母
    name 宠物名
    doggo 狗的成长阶段,分类变量
    floofer 狗的成长阶段,分类变量
    pupper 狗的成长阶段,分类变量
    puppo 狗的成长阶段,分类变量

    通过观察数据,发现一些问题:

    质量

    • column ['in_reply_to_status_id', 'in_reply_to_user_id', 'retweeted_status_id', 'retweeted_status_user_id', 'retweeted_status_timestamp', 'doggo', 'floofer', 'pupper', 'puppo'] 缺少数据
    • timestamp后面多了+0000

    整洁度

    timestamp应该拆分成两列datetime

    image_predict.sample(5)
    

    随机抽取5条图像预测数据观察。各列数据含义如下。

    列名 含义
    tweet_id 档案中的推特 ID
    jpg_url 预测的图像资源链接
    img_num 最可信的预测结果对应的图像编号
    p1 算法对推特中图片的一号预测
    p1_conf 算法的一号预测的可信度
    p1_dog 一号预测该图片是否属于“狗”(有可能是其他物种,比如熊、马等)
    p2 算法对推特中图片预测的第二种可能性
    p2_conf 算法的二号预测的可信度
    p2_dog 二号预测该图片是否属于“狗”
    p3 算法对推特中图片预测的第三种可能性
    p3_conf 算法的三号预测的可信度
    p3_dog 三号预测该图片是否属于“狗”
    extra_data.sample(5)
    

    随机抽取5条转发数等额外数据观察。各列数据含义如下:

    列名 含义
    tweet_id 档案中的推特 ID
    favorite_count 点赞数
    retweet_count 转发数

    编程评估

    twitter_archive.info()
    
    • timestamp应该为datetime类型
    • 数据中包含了转发的数据(retweeted_status_id非空)
    twitter_archive.describe()
    

    rating_numeratorrating_denominator存在异常大的值,且rating_numerator标准差较大。两者需要进一步观察。
    twitter_archive.rating_numerator.value_counts()
    twitter_archive.rating_denominator.value_counts()
    
    部分异常数值:
    420       2
    666       1
    960       1
    1776      1
    Name: rating_numerator, dtype: int64
    110       1
    120       1
    130       1
    150       1
    170       1
    Name: rating_denominator, dtype: int64
    
    • rating_numeratorrating_denominator有三位数和四位数,且数据类型为int
    • 考虑增加一列rating存放\frac{rating\_numerator}{rating\_denominator}
    twitter_archive.source.value_counts()
    
    输出结果:
    <a href="http://twitter.com/download/iphone" rel="nofollow">Twitter for iPhone</a>     2221
    <a href="http://vine.co" rel="nofollow">Vine - Make a Scene</a>                          91
    <a href="http://twitter.com" rel="nofollow">Twitter Web Client</a>                       33
    <a href="https://about.twitter.com/products/tweetdeck" rel="nofollow">TweetDeck</a>      11
    
    • source不需要标签和链接等,保留文本内容即可
    twitter_archive.name.value_counts()
    
    部分输出结果:
    None           745
    a               55
    Charlie         12
    Lucy            11
    Cooper          11
    Oliver          11
    Lola            10
    Penny           10
    Tucker          10
    Winston          9
    Bo               9
    the              8
    Sadie            8
    Bailey           7
    Daisy            7
    Toby             7
    Buddy            7
    an               7
    
    • name缺少部分数据,且有一些名字为aanthe
    • 缺失值填充为None,没有被当成空值
    image_predict.info()
    
    image_predict.describe()
    

    p1预测可信度最高

    #查看是否存在重复预测的图像
    sum(image_predict.jpg_url.duplicated())
    

    结果为66。

    • 存在重复预测的图像
    extra_data.info()
    
    all_columns = pd.Series(list(twitter_archive) + list(image_predict) + list(extra_data))
    all_columns[all_columns.duplicated()]
    

    评估结果

    质量

    twitter_archive table

    • column ['in_reply_to_status_id', 'in_reply_to_user_id', 'retweeted_status_id', 'retweeted_status_user_id', 'retweeted_status_timestamp', 'doggo', 'floofer', 'pupper', 'puppo'] 缺少数据
    • timestamp后面多了+0000
    • timestamp应该为datetime类型
    • 数据中包含了转发的数据(retweeted_status_id非空)
    • rating_numeratorrating_denominator有三位数和四位数,且数据类型为int
    • 考虑增加一列rating存放\frac{rating\_numerator}{rating\_denominator}
    • source不需要标签和链接等,保留文本内容即可
    • name缺少部分数据,且有一些名字为aanthe
    • 缺失值填充为None,没有被当成空值

    整洁度

    • twitter_archive表中的timestamp应该拆分成两列datetime
    • image_predict存在重复预测的图像记录
    • extra_datafavorite_countretweet_count应合入twitter_archive表格中
    • image_predicttwitter_archive合并

    清理

    # 备份
    twitter_archive_clean = twitter_archive.copy()
    image_predict_clean = image_predict.copy()
    

    数据清理每一项都有固定的步骤:定义-代码-测试

    • 定义说明数据存在的问题项,以及该如何解决
    • 代码即根据定义给出的解决方法,进行编写代码
    • 测试即测试是否解决问题

    下面除了第一项给出完整步骤作为例子,后面为了缩减文件幅度,不给出测试步骤

    定义

    ['in_reply_to_status_id', 'in_reply_to_user_id', 'retweeted_status_id', 'retweeted_status_user_id', 'retweeted_status_timestamp'] 缺少数据且不需要用到分析中,直接用drop丢弃掉。['retweeted_status_id', 'doggo', 'floofer', 'pupper', 'puppo'] 暂时保留

    代码

    twitter_archive_clean = twitter_archive_clean.drop(['in_reply_to_status_id', 'in_reply_to_user_id', \
                                'retweeted_status_user_id', 'retweeted_status_timestamp'], axis=1)
    

    测试

    定义

    timestamp后面多了+0000
    用切片舍弃+0000

    代码

    twitter_archive_clean['timestamp'] = twitter_archive_clean.timestamp.str[:-5]
    

    定义

    twitter_archive表中的timestamp应该拆分成两列datetime
    str.split拆分开,然后用drop删除timestamp

    代码

    twitter_archive_clean['timestamp'] = twitter_archive_clean.timestamp.str.strip()
    twitter_archive_clean['date'], twitter_archive_clean['time'] = twitter_archive_clean.timestamp.str.split(" ").str
    twitter_archive_clean.drop('timestamp', axis=1, inplace=True)
    

    定义

    date应该为datetime类型
    to_datetime转换成datetime类型

    代码

    twitter_archive_clean['date'] = pd.to_datetime(twitter_archive_clean['date'])
    

    定义

    数据中包含了转发的数据(retweeted_status_id非空)
    过滤retweeted_status_id非空的行,然后丢弃retweeted_status_id

    代码

    twitter_archive_clean = twitter_archive_clean[twitter_archive_clean['retweeted_status_id'].isnull()]
    twitter_archive_clean.drop('retweeted_status_id', axis=1, inplace=True)
    

    定义

    rating_numeratorrating_denominator有三位数和四位数,且数据类型为int
    rating_numeratorrating_denominator转换成正确的数字,且数据类型改为float

    代码

    twitter_archive_clean.rating_numerator.astype('float64')
    twitter_archive_clean.rating_denominator.astype('float64')
    numBetw20_200 = (twitter_archive_clean['rating_numerator'] > 20) & (twitter_archive_clean['rating_numerator'] <= 200)
    numBeyond200 = twitter_archive_clean['rating_numerator'] > 200
    denoBeyond20 = twitter_archive_clean['rating_denominator'] > 20
    twitter_archive_clean.loc[numBetw20_200, 'rating_numerator'] = twitter_archive_clean.loc[numBetw20_200, 'rating_numerator'] / 10.0
    twitter_archive_clean.loc[numBeyond200, 'rating_numerator'] = twitter_archive_clean.loc[numBeyond200, 'rating_numerator'] / 100.0
    twitter_archive_clean.loc[denoBeyond20, 'rating_denominator'] = twitter_archive_clean.loc[denoBeyond20, 'rating_denominator'] / 10.0
    

    定义

    增加一列rating存放\frac{rating\_numerator}{rating\_denominator}
    计算\frac{rating\_numerator}{rating\_denominator}并存到新列rating

    代码

    twitter_archive_clean['rating'] = twitter_archive_clean['rating_numerator']/twitter_archive_clean['rating_denominator']
    

    定义

    source不需要标签和链接等,保留文本即可
    str.extract提取

    代码

    twitter_archive_clean['source'] = twitter_archive_clean.source.str.extract(r'(?<=\>)(.*?)(?=\<)',expand=True)
    

    定义

    name缺少部分数据,且有一些名字为aanthe
    replacea,an等不是名字的单词替换成np.NaN

    代码

    twitter_archive_clean['name'] = twitter_archive_clean['name'].replace(r'a|an|the|such', np.NaN,regex=True)
    

    定义

    缺失值填充为None,没有被当成空值
    用replace方法将所有None替换成np.NaN

    代码

    twitter_archive_clean = twitter_archive_clean.replace('None', np.NaN)
    

    定义

    image_predict存在重复预测的图像记录,需要删除重复记录

    代码

    image_predict_clean = image_predict_clean[~image_predict_clean.jpg_url.duplicated()]
    

    定义

    extra_datafavorite_countretweet_count应合入twitter_archive表格中
    merge将两表合并

    代码

    twitter_archive_clean = pd.merge(twitter_archive_clean, extra_data, on='tweet_id', how='left')
    

    定义

    image_predicttwitter_archive合并
    merge将两表合并

    代码

    twitter_archive_clean = pd.merge(twitter_archive_clean, image_predict_clean, on='tweet_id', how='inner')
    

    到这里,第一阶段数据清洗完毕。

    再评估


    • 关于狗的地位的信息只有317条,远小于总条数
    • name缺失过多数据
    • source应该为category类型

    再清洗

    定义

    关于狗的地位的信息只有317条,远小于总条数
    text中提取狗的地位存放到stage,然后删掉4列狗的地位

    代码

    twitter_archive_clean['status'] = twitter_archive_clean.text.str.findall('doggo|pupper|puppo|floofer|blep|snoot|floof').apply(lambda x : " ".join(set(x)))
    twitter_archive_clean.drop(['doggo','puppo','pupper','floofer'], axis=1, inplace=True)
    

    定义

    name缺失过多数据
    text中提取狗的名字

    代码

    twitter_archive_clean['name'] = 
      twitter_archive_clean.text.str.extract(r'(?:is\s|Meet\s|to\s)([A-Z][a-z]*)', expand=True)
    

    定义

    source应该为category类型
    astypesource的数据类型换成category

    代码

    twitter_archive_clean['source'] = twitter_archive_clean.source.astype('category')
    

    定义

    将狗的地位为空的记录替换成np.NaN

    代码

    twitter_archive_clean['status'] = twitter_archive_clean['status'].apply(lambda x: np.NaN if len(str(x)) == 0 else x)
    

    清洗完毕后,保存数据。

    # 保存清洗后的数据
    twitter_archive_clean.to_csv('twitter_archive_master.csv', index=None)
    

    可视化分析

    import matplotlib.pyplot as plt
    
    %matplotlib inline
    
    # 读取清洗后的数据
    twitter_archive_master = pd.read_csv('twitter_archive_master.csv')
    
    plt.figure(figsize=(13,5))
    plt.subplot(1,2,1)
    plt.hist(twitter_archive_master.source)
    plt.title('Twitter Data Source Count')
    plt.ylabel('Count')
    plt.xlabel('Source')
    
    plt.subplot(1,2,2)
    plt.pie(twitter_archive_master.source.value_counts(),labels=twitter_archive_master.source.value_counts().index ,autopct='%3.1f %%')
    plt.axis('equal')
    plt.show()
    

    从上面两幅图可以看出,数据绝大多数(98%)来源于Twitter for iPhone(手机客户端),只有小部分来源于桌面应用和浏览器。显而易见的,多数人比较喜欢用Twitter手机客户端来浏览Twitter。
    plt.hist(twitter_archive_master.time.str[:2],bins=24, facecolor='g')
    plt.grid(True)
    plt.title('Period of Comment')
    plt.ylabel('Count of Comments')
    plt.xlabel('Time(h)')
    plt.show()
    

    从用户评论时间来看,最高峰是凌晨一点钟,其次是凌晨十二点,然后是凌晨两点。结合前面数据98%来源于手机客户端,可以看出用户都有睡前玩手机浏览Twitter的习惯。

    plt.boxplot(twitter_archive_master.rating, vert=False, showfliers=False)
    plt.title('Rating Boxplot Without Outliers')
    plt.show()
    


    关于狗的评分平均值是1.05,中位值1.1。也即是说分子评级高于分母评级。并且评分高于1的占79%左右。

    import seaborn as sns
    sns.set_style("white")
    
    sns.set(style="darkgrid")
    sns.lmplot(x='retweet_count', y='favorite_count',data = twitter_archive_master)
    plt.title('retweet_count VS favorite_count')
    plt.show()
    

    转发数与点赞数具有较强的正相关性。其实这也不难得出,毕竟转发或者点赞都是因为喜欢这条tweet才做出的行为。而且转发量大,tweet被人看到的机会也会更大,那么会被点赞的几率也就更大了。



    p1预测比较准确,接下来就用p1来筛选出狗的数据,然后分析哪种类型的宠物狗比较受欢迎。

    # 根据p1的预测结果筛选宠物狗的品种
    df_dogs = twitter_archive_master[['predict1', 'predict1_dog', 'rating', 'favorite_count']]
    df_dogs = df_dogs[df_dogs.predict1_dog == True]
    
    # 根据品种分组,再进行聚合计算,按点赞数从多到少排序
    dogs_summary = df_dogs.groupby('predict1').agg({'rating':'mean', 'favorite_count':'sum'})\
                        .sort_values(by = 'favorite_count', ascending = False)
    # 筛选点赞数最多的前10种宠物狗
    Top10Dogs = dogs_summary.head(10)
    
    # 看favorite_count与rating两者是否相关
    sns.set(style="darkgrid")
    sns.lmplot(x='favorite_count', y='rating',data = dogs_summary)
    plt.title('favorite_count VS rating')
    plt.show()
    

    可以看出favorite_countrating两者相关性很弱。

    相关系数小于0.3,可以视为无线性相关。
    Top10Dogs['favorite_count'].plot(kind = 'bar')
    

    可以看到获得点赞数最多的宠物狗类型是golden_retriever,也就是金毛啦。性格温顺,且比较体贴的金毛当然比较受欢迎,我也喜欢金毛。

    反思

    在数据清洗时,对一些异常数据进行处理,例如评分,可能对后面的分析造成了影响,例如可能影响到了后面得出评分与点赞数无相关的结论。后续应该多思考,如何进行数据清洗可以使得结论更加准确,而不用担心得出错误的结论。

    相关文章

      网友评论

          本文标题:清洗与分析数据Dog_rates

          本文链接:https://www.haomeiwen.com/subject/hsiuwqtx.html