import pandas as pd
import numpy as np
import requests
import matplotlib.pyplot as plt
import re
import seaborn as sns
%matplotlib inline
pd.options.display.max_columns=10
数据收集
#用pd.read_csv来读取twitter-archive-enhanced.csv内的信息并保存到twitter_archive_enhanced中
twitter_archive_enhanced = pd.read_csv('twitter-archive-enhanced.csv')
#利用requests库来下载文件,并保存到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'
r = requests.get(url)
with open(url.split('/')[-1],'wb') as f:
f.write(r.content)
#用pd.read_csv来读取image-predictions.tsv内的信息并保存到image_predictions中
image_predictions = pd.read_csv('image-predictions.tsv',sep='\t')
#建一个空的列表,用来保存信息,并在之后用于转换成t_data
#这里的json文件直接使用了优达学城提供的数据
t_data_list = []
with open('tweet_json.txt') as f:
for line in f:
""""
这里用正则表达式来提取json文件中的相应字段
观察json文件,以第一行为例:
"id": 892420643555336193 "retweet_count": 8842, "favorite_count": 39492
所使用的三个字段分别以上面的形式给出,因此对应的正则表达式pattern可以分别写作
r'"id": \d+'
r'"retweet_count"
r'"favorite_count": \d+'
之后进行提取
"""
i_d = str(re.search(r'"id": \d+',line).group(0)[6:])
retweetCount = int(re.search(r'"retweet_count": \d+',line).group(0)[17:])
favoriteCount = int(re.search(r'"favorite_count": \d+',line).group(0)[18:])
"""
储存到list中
"""
t_data_list.append({'tweet_id':i_d,
'retweet_count':retweetCount,
'favorite_count':favoriteCount})
"""
转换
"""
t_data = pd.DataFrame(t_data_list,columns=['tweet_id','retweet_count','favorite_count'])
这里也可以使用read_json方法
#尝试使用read_json方法
t_data1 = pd.read_json('tweet_json.txt',lines=True)
t_data1 = t_data1[['id', 'retweet_count', 'favorite_count']].copy()
t_data1.rename(columns = {'id':'tweet_id'})
数据评估
#显示twitter_archive_enhanced中的前30行
twitter_archive_enhanced.head(30)
#显示twitter_archive_enhanced中的后30行
twitter_archive_enhanced.tail(30)
1.观察了前后30行发现,source列中还保留着html标签。
2.在retweeted_status_user_id列中发现了不为零的项,需要在info()信息中确认有多少转发。
3.与stage相关的列有大量缺失。
#显示twitter_archive_enhanced的info
twitter_archive_enhanced.info()
从这里可以发现:
1.tweet_id,in_reply_to_status_id,in_reply_to_user_id,timestamp等列的数据类型存在问题。
2.in_reply_to_status_id,in_reply_to_user_id两列缺失值过多,应该删除。
3.retweeted_status_id等与转发相关的列不为空白,说明存在表中转发的情况,需要删除。
4.doggo,floofer,pupper,puppo等代表狗的stage的列不应该单独存在,应该合并起来。
5.expanded_urls有缺失项。
#察看统计信息
twitter_archive_enhanced.describe()
#利用正则表达式统计评分为小数,并且不是转发twitter
twitter_archive_enhanced_ = twitter_archive_enhanced.loc[twitter_archive_enhanced.text.str.extract(r'(\d+\.\d+/)',re.S,expand=True).notnull()[0]]
twitter_archive_enhanced_.loc[twitter_archive_enhanced_.retweeted_status_id.isnull()]
发现有一些打分是小数,而统计评分均为整数
twitter_archive_enhanced_.loc[twitter_archive_enhanced_.retweeted_status_id.isnull()].index
一共有五条,index为45,695,763,1689,1712
twitter_archive_enhanced.name.value_counts()
发现有些狗狗没有名字
#显示image_predictions中的前10行
image_predictions.head(10)
#察看狗的种类
image_predictions.p1.value_counts()
#显示image_predictions的info
image_predictions.info()
#显示t_data中的前10行
t_data.head(10)
#显示t_data中的描述统计信息
t_data.describe()
#显示t_data的info
t_data.info()
sum(image_predictions.tweet_id.duplicated())
0
#察看分母
twitter_archive_enhanced.rating_denominator.value_counts()
可以发现评分列中存在着各种分母不为10的情况,需要观察。
数据质量:
twitter_archive_enhanced表
1.包含转发的信息。
2.expanded_urls有缺失项。
3.有些狗的明字是the/a/an这些显然不太可能的名字。
4.stage列中存在大量缺失了。
5.source列中有不需要的html标签。
6.in_reply_to_status_id,in_reply_to_user_id缺失项过多需要删除。
7.评分列中存在着各种分母不为10的情况,需要观察。
8.存在个别评分分子为小数。
9.tweet_id,in_reply_to_status_id,in_reply_to_user_id,timestamp等列的数据类型存在问题。
image_predictions表
10.image_predictions表中的图片url存在重复。
11.tweet_id列的数据类型不正确。
t_data表
未发现
数据整洁度:
1.代表狗stage的变量这个本来只需要一列的变量,在四列中表示了。
2.应该将image_predictions与t_data这两个表格应该与twitter_archive_enhanced合并。
清洗中发现的问题:
发现text中存在&这个html的用于表示&的信息,需要删除。
数据清洗
#复制数据集,将twitter_archive_enhanced复制到为main_clean
main_clean = twitter_archive_enhanced.copy()
image_predictions_clean = image_predictions.copy()
t_data_clean = t_data.copy()
定义:删除转发的信息
代码
#删除转发信息
main_clean = main_clean.loc[main_clean.retweeted_status_id.isnull()]
main_clean.drop(['retweeted_status_id','retweeted_status_user_id','retweeted_status_timestamp'],axis=1,inplace=True)
测试
#检查删除结果
main_clean.info()
定义:删除expanded_urls缺失的行
代码
#删除expanded_urls缺失的行
main_clean = main_clean.loc[main_clean.expanded_urls.notnull()]
测试
#检查删除结果
main_clean.info()
定义:将name列中的a,the,an,None等名字转换为np.nan
代码
#将a,the,an等名字转换为np.nan
replace=['a','the','an','None']
for name in replace:
main_clean['name'] = main_clean['name'].replace(name,np.nan)
测试
#检查结果
main_clean['name'].value_counts()
定义:text中提取与stage有关的信息,并合并成一列(使用修改意见中的从text中提取的方法)
代码
#将stage有关的信息并合并成一列
main_clean['stage'] = main_clean.text.str.lower().str.findall(r'(doggo|floof|pupper|puppo)')
main_clean['stage'] = main_clean.stage.apply(lambda x:set(x))
main_clean['stage'] = main_clean.stage.apply(lambda x:'|'.join(x))
main_clean['stage'] = main_clean.stage.replace('',np.nan)
main_clean.drop(['doggo','floofer','pupper','puppo'],axis=1,inplace = True)
测试
#检查结果
main_clean.info()
定义:删除source列中的html标签
代码
#删除source列中的html标签
main_clean['source'] = main_clean.source.str.extract(r'>(.*)<',re.S,expand=True)
测试
#检查结果
main_clean['source'].value_counts()
定义:删除in_reply_to_status_id,in_reply_to_user_id列
代码
#删除in_reply_to_status_id,in_reply_to_user_id列
main_clean.drop(['in_reply_to_status_id','in_reply_to_user_id'],axis=1,inplace=True)
测试
#检查结果
main_clean.info()
定义:从text中察看评分列中存在着各种分母不为10的行的具体情况(使用修改意见中stage的修改方法后,此处的行的index变了,对于新的index重新进行了赋值操作)
代码
#察看分母不为10的
main_clean.loc[main_clean.rating_denominator!=10,['text','rating_denominator']]
从观察中可以发现,433,902,1120,1016,1228,1254,1274,1351,1433,1634,1635,1779,1843的分母大于10并没有问题,因为这些都是因为不止有一只狗造成的原因。
516也没有问题,因为给的评分就是24/7。
1068存在问题,9/11并不是这只狗的分数,实际分数14/10。
1165存在问题,实际的分数是13/10。
1202存在问题,实际的分数是11/10。
1662存在问题,实际分数是10/10。
2335存在问题,实际分数是9/10。
同时发现text中存在amp;这个html的用于表示&的信息,需要删除。
#对于评分进行更改
dic={1068:[14,10],1165:[13,10],1202:[11,10],1662:[10,10],2335:[9,10]}
for key,value in dic.items():
main_clean.loc[key,['rating_numerator','rating_denominator']] = dic[key]
测试
#检查修改
for key in dic.keys():
print(main_clean.loc[key,['rating_numerator','rating_denominator']])
定义:对于text中的amp;进行删除
代码
#对于text中的amp;进行删除
main_clean['text'] = main_clean.text.str.replace("&","")
测试
#检查结果
main_clean[main_clean.text.str.contains('&')]
定义:修改tweet_id,timestamp列的数据类型
代码
#修改tweet_id,timestamp列的数据类型
main_clean['tweet_id'] = main_clean.tweet_id.astype(str)
main_clean['timestamp'] = pd.to_datetime(main_clean.timestamp)
测试
#检查结果
main_clean.info()
定义:将rating_numerator类型改为float,并且修改评分分子为小数的数据
代码
#提取小数结果
main_clean.loc[main_clean.text.str.extract(r'(\d+\.\d+/)',re.S,expand=True).notnull()[0],'text']
#修改类型,察看text中的原始数据,用main_clean_clean_float来储存分子为小数的行
main_clean['rating_numerator'] = main_clean.rating_numerator.astype(float)
main_clean_float = main_clean.loc[main_clean.text.str.extract(r'([;\s(]([0-9]+?/[0-9]+)|(^[0-9]+?/[0-9]+)|(\.\.\.[0-9]+?/[0-9]+)|(\D\.[0-9]+?/[0-9]+))',re.S,expand=True).isnull()[0]]
for i in main_clean_float.index:
print('{}:'.format(i)+main_clean_float.loc[i].text)
#由上面得到的数值,对相应的行进行修改
dic = {45:13.5,695:9.75,763:11.27,1712:11.26}
for index,val in dic.items():
main_clean.loc[index,"rating_numerator"]=dic[index]
测试
#检查结果
for index in dic.keys():
print(main_clean.loc[index,"rating_numerator"])
定义:删除image_predictions表中重复的url
代码
#删除图片url的重复
image_predictions_clean.drop_duplicates('jpg_url',inplace=True)
检查
#检查结果
sum(image_predictions_clean.jpg_url.duplicated())
0
定义:修改image_predictions_clean中修改tweet_id列的数据类型
代码
#修改tweet_id列的数据类型
image_predictions_clean['tweet_id'] = image_predictions_clean['tweet_id'].astype(str)
测试
#检查结果
image_predictions_clean.info()
定义:合并三个数据集
代码
#合并三个数据集
df_clean = main_clean.merge(image_predictions_clean,how='inner',on='tweet_id')
df_clean = df_clean.merge(t_data,how='left',on='tweet_id')
测试
#察看合并后结果
df_clean.info()
#察看合并后结果
df_clean.head()
数据存储
df_clean.to_csv('twitter_archive_master.csv', index=False)
数据分析和可视化
提出问题:
1.favorite_count与retweet_count之间存在什么关系吗?
2.在数据已知的stage中,哪个stage占比最高?
3.从神经网络的结果中,哪个种类的狗最受欢迎?
4.能判别性别的狗中,是公的多还是母的多?
#导入数据
df = pd.read_csv('twitter_archive_master.csv')
df.info()
1.favorite_count与retweet_count之间存在什么关系吗?
plt.figure(figsize=(8,8))
plt.scatter(df['favorite_count'],df['retweet_count'])
plt.xlabel('favorite_count')
plt.ylabel('retweet_count')
plt.title('relationship between favorite_count and retweet_count')
从图中可以发现favorite_count与retweet_count有很强的正相关性,favorite_count数越高,retweet_count也相应越高。
fig,ax = plt.subplots(figsize=(8,8))
sns.heatmap(df[['favorite_count','retweet_count','rating_numerator']].corr(),annot=True,ax=ax)
plt.title('Correlation Map')
从相关性图中,可以发现favorite_count与retweet_count的相关系数到达了0.92这个接近1的数值,更加说明了两者之间强的正相关性。同时,两者与rating nummerator的相关系数较小,说明没有明显的线形关系。
2.在数据已知的stage中,哪个stage占比最高?(更新数据后将图标更新)
#将有多个状态的狗地数据变成多行并保存到stage_count中,并将index保存到labels中
stage_count = df.stage.str.split('|',expand=True).stack().value_counts()
labels = df.stage.str.split('|',expand=True).stack().value_counts().index.tolist()
plt.figure(figsize=(8,8))
explode = (0.2,0,0,0)
plt.pie(stage_count,labels=labels,explode = explode,autopct = '%3.1f%%',shadow = True,startangle = 90)
plt.axis('equal')
plt.title('pie of stage')
可以看出在已知的stage中,pupper占最多的比例。
3.从神经网络的结果中,哪个种类的狗最受欢迎?
#提取狗的种类
count = []
for index in df.index:
if df.loc[index]['p1_dog'] == True:
count.append(df.loc[index]['p1'])
elif df.loc[index]['p2_dog'] == True:
count.append(df.loc[index]['p2'])
elif df.loc[index]['p3_dog'] == True:
count.append(df.loc[index]['p3'])
count = pd.Series(count)
count_top10 = count.value_counts()[:10]
count_top10
count_top10.plot(kind = 'bar',figsize=(16,8),rot=0,)
plt.title('top10 famous dogs')
从表中可以看出大家都喜欢金毛猎犬和拉不拉多犬这类性格温顺又聪明的狗。
4.能判别性别的狗中,是公的多还是母的多?
#提取狗的性别
g_male = ['He','he','His','his','him',"he's","He's",'himself']
g_female = ['She','she','Her','her',"she's","She's",'herself']
gender=[]
for str_ in df['text']:
if any(map(lambda x:x in g_male,str_.split())):
gender.append ('male')
elif any(map(lambda x:x in g_female,str_.split())):
gender.append ('female')
gender = pd.Series(gender)
gender.value_counts()
#进行绘图
plt.figure(figsize=(8,8))
labels = ['male','female']
explode = (0.2,0)
plt.pie(gender.value_counts(),labels=labels,explode = explode,autopct = '%3.1f%%',shadow = True,startangle = 90)
plt.axis('equal')
plt.title('pie of sex of dogs')
从这个结果可以看出公狗占大多数。