美文网首页
清洗与分析数据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