WerateDogs数据分析

这是我的第一个数据分析项目,主要是对WerateDogs(一个以诙谐幽默的方式为狗狗评分的tweet)的数据进行收集和清洗,并生成可视化。
原创,禁止转载!

import pandas as pd
import numpy as np
import requests as rq
import tweepy
import json
import os
#设置数据的显示长度为500字符
pd.set_option('max_colwidth',500)
#读取twitter-archive-enhanced.csv文件,简写为tae
tae=pd.read_csv('twitter-archive-enhanced.csv')
tae[tae['retweeted_status_id'].notnull().values==True]

数据质量问题:

twitter-archive-enhanced表

  1.timestamp列和retweeted_status_user_id列的时间后面都有'+0000';
  2.source列有多余的html相关信息,只需要截取设备相关信息;
  3.与转发推文相关的列应该删除,根据项目要求没有相关图片的列也需要删除;
tae.info()

数据质量问题:

twitter-archive-enhanced表

4.所有“id”相关的数据类型应该是字符串,所有“timesatmp”相关的数据类型应该是Date type;
5.expanded_urls部分缺失,后续应该删除;
6.doggo、floofer、pupper、puppo列有大量空值,有的一个dogname对应2种stage。

数据整洁度问题:

twitter-archive-enhanced表

1.doggo、floofer、pupper、puppo四列应该合并成‘stage’一列
#首先查重,没有重复行
tae.duplicated()
tae['tweet_id'].duplicated().sum()
tae['text'].duplicated().sum()
#查询跟expanded_urls相关的缺失,应该是因为相关列属于转发列,所以没有url,后续删除。
tae[tae['expanded_urls'].isnull().values==True]
tae['text'].sort_values(0)
tae['expanded_urls'].value_counts()
tae['expanded_urls'].sort_values()

数据整洁度问题:

twitter-archive-enhanced表:

2.expanded_urls列出现很多重复的url;
tae['rating_numerator'].sample(100)
tae['rating_numerator'].value_counts()
tae['rating_numerator'].isnull().sum()
tae['rating_numerator'].sort_values()

数据质量问题:

twitter-archive-enhanced表:

7.rating_numerator列狗的评分有0分,还有很多评分达到三位数甚至4位数(观察发现可能是跟前面的text列出现的评分错误有关),还有空值;
tae['rating_denominator'].value_counts()
tae['rating_denominator'].sort_values()

数据质量问题:

twitter-archive-enhanced表:

  8.rating_denominator列很多基准评分是10分以上,甚至出现3位数(暂未知是否正确),有空值出现。
tae['name'].sample()
tae['name'].value_counts()
tae['name'].sort_values()

数据质量问题:

twitter-archive-enhanced表

  9.name列出现很多非名字的单词、字母‘a’或空值;
#创建一个文件夹,下载image-predicitons文件
folder_name = 'image-predictions'
if not os.path.exists(folder_name):
    os.makedirs(folder_name)
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'
response=rq.get(url)
with open(os.path.join(folder_name,url.split('/')[-1]),mode='wb') as file:
    file.write(response.content)
#读取image-predictions文件
ip=pd.read_csv('image-predictions/image-predictions.tsv',sep='\t')

数据质量问题:

image-predictions表

  10.tweet_id的类型应为字符串,而不是整形;
ip.duplicated()
ip['jpg_url'].duplicated().sum()

数据质量问题:

image-predictions表

  11.jpg_url列出现65条重复的url,应该是转发的,删除;
#读取tweet_json文件
tweet=pd.read_json('tweet_json.txt',lines=True)
tweet.info()
#这里只需要id、favorite count和retweet相关的数据,先观察一下数据
tweet[['id','id_str','favorite_count','retweeted','retweet_count']].sample(100)
#id和id_str两列有些末两位数字不一样;retweeted列没有数据,删除。
tae['tweet_id'].isin([714251586676113408,692894228850999296]).sum()
#随机选择id和id_str列两组不一致的数据检查,发现id列的数据是对的而id_str列是错的
#根据tweet新建DataFrame,并将tweet_id类型改为字符串,为后面合并表格做准备
tweet_clean=tweet.copy()
tweet_clean=pd.DataFrame(tweet_clean[['id','favorite_count','retweet_count']])
tweet_clean.rename(columns={'id':'tweet_id'},inplace=True)
tweet_clean['tweet_id']=tweet_clean['tweet_id'].astype('str')

数据质量问题:

twitter-archive-enhanced表

  1.timestamp列和retweeted_status_user_id列的时间后面都有'+0000';
  2.source列有多余的html相关信息,只需要截取设备相关信息;
  3.与转发推文相关的行和列应该删除;
  4.所有“id”相关的数据类型应该是字符串,所有“timesatmp”相关的数据类型应该是Date type;
  5.expanded_urls部分缺失;
  6.doggo、floofer、pupper、puppo列有大量空值,有的一个dogname对应2种stage;
  7.rating_numerator列狗的评分有0分,还有很多评分达到三位数甚至4位数(观察发现可能是跟前面的text列出现的评分错误有关),还有空值;
  8.rating_denominator列很多基准评分不是10分,基准评分出现3位数(暂未知是否正确),有空值出现;
  9.name列出现很多非名字的单词、字母‘a’或空值;

image-predictions表

  10.tweet_id应是字符串,而不是整形;
  11.jpg_url列出现65条重复的url,应该是转发的,删除;

数据整洁度问题:

twitter-archive-enhanced表:

  1.doggo、floofer、pupper、puppo四列应该合并成‘stage’一列;
  2.expanded_urls列出现很多重复的url;
  3.应该依据tweet_id将三个表格合并到一个表格中。

#1.timestamp列和retweeted_status_user_id列的时间后面都有’+0000’;
后面要删除retweeted_status_user_id列,就不修改这一列了。

#先将所有表格copy一份
tae_clean=tae.copy()
ip_clean=ip.copy()
tweet_clean=tweet_clean.copy()
#tae_clean.info()
tae_clean['timestamp']=tae_clean['timestamp'].astype('str')
tae_clean['timestamp']=tae_clean['timestamp'].str[0:19]
tae_clean['timestamp']

#2.source列有多余的html相关信息,只需要截取设备相关信息;

tae_clean['source'].value_counts(0)
tae_clean['source']=tae_clean['source'].str.extract('(>(.+)<)',expand=True)
tae_clean['source']=tae_clean['source'].str.extract('([A-Z]\D+[a-z])',expand=True)
#测试结果
tae_clean['source'].value_counts()

#3.与转发推文相关的行和列应该删除,没有图片的列也应该删除;观察发现retweet相关的列的时间都更早一些,但是不确定是否是最初的tweet,所以直接删除,共删除in_reply_to_status_id、in_reply_to_user_id、retweeted_status_id、retweeted_status_user_id、retweeted_status_timestamp5列及对应的
行。没有图片的列将在后面合并三个表格时再处理。

#先看下in_reply_to_status_id和retweet相关的各有多少列
tae_clean[tae_clean['in_reply_to_status_id'].notnull()]
tae_clean[tae_clean['retweeted_status_id'].notnull()]
in_reply_to_status_id和retweet相关的依次有78181,有部分重叠的,都删除掉
#先保留非转发的数据
tae_clean=tae_clean[tae_clean['retweeted_status_id'].isnull()]
tae_clean=tae_clean[tae_clean['in_reply_to_status_id'].isnull()]
#删除in_reply_to_status_id、in_reply_to_user_id、retweeted_status_id、retweeted_status_user_id、retweeted_status_timestamp5列
tae_clean.drop(['in_reply_to_status_id','in_reply_to_user_id','retweeted_status_id','retweeted_status_user_id','retweeted_status_timestamp'],axis=1,inplace=True)
#测试结果
tae_clean.info()

#4所有“id”相关的数据类型应该是字符串,所有“timesatmp”相关的数据类型应该是Date type;

#将tweet_id改为字符串
tae_clean['tweet_id']=tae_clean['tweet_id'].astype('str')
#将timestamp改为date time型式
import time,datetime
tae_clean['timestamp']=tae_clean['timestamp'].apply(lambda x:datetime.datetime.strptime(x, "%Y-%m-%d %H:%M:%S") )
tae_clean['timestamp']
#测试结果
tae_clean.info()

#5.expanded_urls部分缺失; 现在expanded_urls只剩下3个空值。

#先观察空值情况
tae_clean[tae_clean['expanded_urls'].isnull()]
#相关行的name也是空值,全部删除
tae_clean=tae_clean[tae_clean['expanded_urls'].notnull()]
#测试结果
tae_clean['expanded_urls'].value_counts()

#6.doggo、floofer、pupper、puppo列有大量空值,有的一个dogname对应2种stage。待name列处理完后再处理这一条。

#7、#8 .rating_numerator、rating_denominator列评分较多错误。先从text列提取相关评分对比观察,并相应调整。

#从text列提取评分相关数据,使用正则表达式\d+\/\d+来匹配评分,如果text里面有多个类似字符串,可能会匹配第一个,造成数据错误,后面进一步更正
tae_clean['rating_standard']=tae_clean['text'].str.extract('(\d+\/\d+)',expand=True)
tae_clean['rating_standard'].value_counts()
#针对其中可能有异常的值观察下text的内容
tae_clean[tae_clean['rating_standard'].isin(['27/10','26/10','84/70','121/110','50/50','9/11','1776/10','7/11','45/50','4/20','24/7','80/80','88/80','1/2','75/10','144/120','420/10','60/50','44/40','204/170','99/90','165/150'])][['text','rating_standard','rating_numerator','rating_denominator']]
#其中出现了一些分母不为10的情况,大部分可以人为将分母调整为10,分子对应调整;但是像50/50、24/7、9/11、4/20、1/2和7/11这样的是截取了错误的数据,像26/10、75/10和27/10是只截取了小数部分数据,都要进行调整。
tae_clean['rating_standard'].replace({'24/7':'nan','45/50':'9/10','144/120':'12/10','88/80':'11/10','204/170':'12/10','121/110':'11/10','99/90':'11/10','84/70':'12/10','4/20':'13/10','80/80':'10/10','9/11':'14/10','44/40':'11/10','1/2':'9/10','165/150':'11/10','60/50':'12/10','50/50':'11/10','7/11':'10/10','4/20':'13/10','75/10':'11.75/10','27/10':'11.27/10','26/10':'11.26/10'},inplace=True)
tae_clean[tae_clean['rating_denominator']!=10]
#所有错乱数据都已经更正,接下来将rating_standards列拆分,取代原来的rating_numerator、rating_denominator列
tae_clean['rating_numerator_new'],tae_clean['rating_denominator_new']=tae_clean['rating_standard'].str.split('/',n=1).str
#测试结果
tae_clean['rating_numerator_new'].value_counts()
tae_clean['rating_denominator_new'].value_counts()
#对于其中1776和420这两个可能异常的值再次观察对应的text文本,发现评分确实是这么高,不属于异常。
#删除原来的rating_numerator、rating_denominator列
tae_clean.drop(['rating_numerator','rating_denominator'],axis=1,inplace=True)
tae_clean
#至此评分清洗完毕

#9.name列出现很多非名字的单词、字母‘a’或空值。

tae_clean['name'].value_counts()
#其中有600个空值和55个a,可以通过提取text栏信息进一步完善;仔细观察text,发现类似于This is、named、Meet、Say hello to、name is、Here we have、
# Here is等字符后面跟的都是dog的姓名,都在text的首句。因此采用(?:This is|named|Meet|Say hello to|name is|Here we have|Here is)\s([A-Z][a-z.+]*)(|表示从前面的字符串里面
#任选一个作为前缀,[A-Z][a-z.+]*表示以大写字母开头、后面紧跟小写字母、到后面一个'.'为止的狗的名字)匹配狗的名字,再利用切片去除后面的‘.’。
tae_clean['name_new']=tae_clean['text'].str.extract('(?:This is|named|Meet|Say hello to|name is|Here we have|Here is)\s([A-Z][a-z.+]*)',expand=True)
tae_clean['name_new'].value_counts()
#用nan填充空白
tae_clean['name_new']=tae_clean['name_new'].str[:-1].replace('',np.nan)
tae_clean['name_new'].sample(100)
#删除原来name列
tae_clean.drop(['name'],axis=1)

#6.doggo、floofer、pupper、puppo列有大量空值,有的一个dogname对应2种stage;同时存在整洁度问题,应该将他们合并成‘satge’一列。从text重新提取相关信息生成stage列。

#从text提取stage相关信息
tae_clean['stage']=tae_clean['text'].str.lower().str.findall('(doggo|floofer|pupper|puppo)')
#将stage列的值改为str,并合并有两个或三个stage的值
tae_clean['stage']=tae_clean['stage'].apply(lambda x:','.join(set(x))).replace('',np.nan)
tae_clean['stage'].value_counts()
#删除doggo、floofer、pupper、puppo列
tae_clean.drop(['doggo','floofer','pupper','puppo'],axis=1,inplace=True)
tae_clean['stage'].value_counts()
#其中有一些stage里面有两种评级,将其拆分为两行。
#新建一列,先将有两个stage的值拆分为两行
stage_split=tae_clean['stage'].str.split(',',expand=True).stack()
#重新设置索引
stage_split=stage_split.reset_index(level=1,drop=True)
#删除含多值的列,然后把拆分后的列合并进去
tae_clean=tae_clean.drop('stage',axis=1).join(stage_split.rename('stage'))
tae_clean['stage'].value_counts()

###image-predictions表
10.tweet_id应是字符串,而不是整形

ip_clean['tweet_id']=ip_clean['tweet_id'].astype('str')
ip_clean.info()

#11.jpg_url列出现65条重复的url,应该是转发的,删除;

ip_clean.drop_duplicates(['jpg_url'],'first',inplace=True)
#测试结果
ip_clean['jpg_url'].value_counts()

数据整洁度问题:

twitter-archive-enhanced表:
1.已将dog的四个评级列合并成一列;
2.expanded_urls列出现很多重复的url;这一列信息与后面的分析没什么关系,可以删除

tae_clean.drop(['expanded_urls'],axis=1,inplace=True)
tae_clean

#2.应该依据tweet_id将三个表格合并到一个表格中;项目要求使用含有图片的原始评级,因为jpg_url列都是含图片的,这里采用inner连接即可过滤掉相关无图片的行。

#tweet_clean.info()
tae_clean=pd.merge(tae_clean,ip_clean,on=['tweet_id'],how='inner')
tae_clean=pd.merge(tae_clean,tweet_clean,on='tweet_id',how='left')
tae_clean
#删除text,name,rating_standard列,修改对应列名后存档
tae_clean.drop(['text','name','rating_standard'],axis=1,inplace=True)
tae_clean.rename(columns={'rating_numerator_new':'rating_numerator','rating_denominator_new':'rating_denominator','name_new':'name'},inplace=True)

储存数据

tae_clean.to_csv('twitter_archive_master.csv')

数据分析和可视化

拟研究的问题:
1.狗的评分是否与转发数和点赞数有关;
2.狗的哪几个名字最常用;
3.狗的哪种评级的评分最高。
#首先加载数据
df=pd.read_csv('twitter_archive_master.csv')
df
import matplotlib.pyplot as plt
%matplotlib inline

#1. 狗的评分是否与转发数和点赞数有关;

df_favorite=df[['favorite_count','rating_numerator']]
#评分存在异常值,这里取评分低于30分的值
df_favorite=df[df['rating_numerator']<30]
#这里选用散点图
plt.scatter(df_favorite['rating_numerator'],df_favorite['favorite_count'])
plt.xlabel('rating_numerator')
plt.ylabel('favorite_count')
plt.title('scatter')
plt.show()
df_favorite=df[['retweet_count','rating_numerator']]
#评分存在异常值,参考上面的结果,这里取评分低于20分的值
df_favorite=df[df['rating_numerator']<20]
plt.scatter(df_favorite['rating_numerator'],df_favorite['retweet_count'])
plt.xlabel('rating_numerator')
plt.ylabel('retweet_count')
plt.title('scatter')
plt.show()

在评分较为正常的区域(低于15分),随着favorite_count、retweet_count分布越密集、数值越大,则评分越高,说明点赞数、转发数与评分正相关,
也可能是因为评分越高则点赞和转发越高。

#2 狗的哪几个名字最常用;采用词云图来观察;

# -*- coding=utf-8 -*-
from wordcloud import WordCloud
from wordcloud import ImageColorGenerator
from os import path
import numpy as np
from PIL import Image
import matplotlib.pyplot as plt
%matplotlib inline
df_name=df[['tweet_id','name']].dropna()
df_name['name'].sort_values()
image=Image.open(r"music.png")
img=np.array(image)
cloud=WordCloud(font_path='geforce.ttf',background_color='white',mask=img,max_words=200,max_font_size=300,width=1400,height=2400)
names='/'.join(df_name['name'])
print(names)
cloud.generate(names)
plt.imshow(cloud)
plt.axis('off')
plt.show()
plt.savefig('dog_name.png',dpi=300)

WerateDogs数据分析_第1张图片


从词云图看,最常用的名字包括Charlie,Dliver,Lucy,Cooper,Penny等,还可以进一步搜集dog的性别信息,统计这些常用名与性别的关系。

#3.狗的哪种评级的评分最高。需要求出各种分级评分的均值再进行比较。

df_stage=df[['stage','rating_numerator']]
df_stage.groupby('stage').mean().sort_values('rating_numerator',ascending=False)

从统计结果看,puppo的平均评分最高,后面依次是floofer,doggo和pupper。由于评级相关的数据较少统计结果可能存在一定的误差。

##总结:通过加载、url下载方式收集了Weratedgos相关的三份数据,经过评估后对三份数据进行了清理和合并,最后利用matplotlib画散点图研究了相关转发数、点赞数与狗的评分的关系,画词云图研究了狗的哪些名字最常见,通过pandas统计的不同stage狗的评分的高低排序。

你可能感兴趣的:(数据分析)