我已经分享了本书的ipynb,所以跟着我一起来实验吧。如果你不懂怎么打开ipynb格式的文件,那也没关系,anaconda3让一切变得更简单(我像是打广告的)。
安装玩anaconda之后,我们在开始里就可以找到它的文件夹,里面有一个Jupyter Notebook,就是它了。点开之后,弹出cmd的黑窗口,接着浏览器弹出网页,那么就启动成功了(这里别去关掉cmd的黑窗口,最小化就行),它的主页一般定位在“我的文档”,所以,为了方便起见,把你下载好的ipynb文件放到“我的文件”下,解压成文件夹即可在浏览器中点击查看。
我们处理数据,基本都要完成以下几大任务:
来自bit.ly的1.usa.gov数据
数据简单介绍:2011年,URL缩短服务bit.ly跟美国政府网站usa.gov合作,提供了一份从生成.gov或.mil短链接的用户那里收集来的匿名数据。除实时数据之外,还可以下载文本形式的每小时快照。以每小时快照为例,文件中各行的格式为JSON。
例如,如果我们只读取某个文件中的第一行,那么你所看到的结果应该是下面这样:
path = 'ch02/usagov_bitly_data2012-03-16-1331923249.txt' open(path).readline()
输出结果如下:
'{ "a": "Mozilla\\/5.0 (Windows NT 6.1; WOW64) AppleWebKit\\/535.11 (KHTML, like Gecko) Chrome\\/17.0.963.78 Safari\\/535.11", "c": "US", "nk": 1, "tz": "America\\/New_York", "gr": "MA", "g": "A6qOVH", "h": "wfLQtf", "l": "orofrog", "al": "en-US,en;q=0.8", "hh": "1.usa.gov", "r": "http:\\/\\/www.facebook.com\\/l\\/7AQEFzjSi\\/1.usa.gov\\/wfLQtf", "u": "http:\\/\\/www.ncbi.nlm.nih.gov\\/pubmed\\/22415991", "t": 1331923247, "hc": 1331822918, "cy": "Danvers", "ll": [ 42.576698, -70.954903 ] }\n'
我们可以读取json文件后用列表推导式将文件转化为列表,以下是转为列表和读取列表的操作:
import json path = 'ch02/usagov_bitly_data2012-03-16-1331923249.txt' records = [json.loads(line) for line in open(path)] records[0] records[0]['tz']
以下是输出的结果
{'a': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.78 Safari/535.11', 'al': 'en-US,en;q=0.8', 'c': 'US', 'cy': 'Danvers', 'g': 'A6qOVH', 'gr': 'MA', 'h': 'wfLQtf', 'hc': 1331822918, 'hh': '1.usa.gov', 'l': 'orofrog', 'll': [42.576698, -70.954903], 'nk': 1, 'r': 'http://www.facebook.com/l/7AQEFzjSi/1.usa.gov/wfLQtf', 't': 1331923247, 'tz': 'America/New_York', 'u': 'http://www.ncbi.nlm.nih.gov/pubmed/22415991'}
'America/New_York'
对时区进行计数,假设我们想要知道该数据集中最常出现的是哪个时区(即tz字段)
from pandas import DataFrame import json path = 'ch02/usagov_bitly_data2012-03-16-1331923249.txt' records = [json.loads(line) for line in open(path)] frame=DataFrame(records) tz_counts=frame['tz'].value_counts() #print(tz_counts[:10]) #以下是对空缺值的清洗 clean_tz=frame['tz'].fillna(value='Missing') clean_tz[clean_tz ==''] = 'Unknown' tz_counts=clean_tz.value_counts() print(tz_counts[:10])
输出结果:
America/New_York 1251 Unknown 521 America/Chicago 400 America/Los_Angeles 382 America/Denver 191 Missing 120 Europe/London 74 Asia/Tokyo 37 Pacific/Honolulu 36 Europe/Madrid 35 Name: tz, dtype: int64
最常出现的10个时区的水平条形图代码:
from matplotlib import pyplot as plt tz_counts[:10].plot(kind='barh',rot=0) plt.show()
然后,我们来看一下里面的“a”字段,用字符串函数和正则表达式将里面信息解析出来,统计最常用的几个浏览器
from pandas import DataFrame,Series from matplotlib import pyplot as plt import json path = 'ch02/usagov_bitly_data2012-03-16-1331923249.txt' records = [json.loads(line) for line in open(path)] frame=DataFrame(records) results=Series([x.split()[0] for x in frame.a.dropna()]) print(results.value_counts()[:8])
输出结果:
Mozilla/5.0 2594 Mozilla/4.0 601 GoogleMaps/RochesterNY 121 Opera/9.80 34 TEST_INTERNET_AGENT 24 GoogleProducer 21 Mozilla/6.0 5 BlackBerry8520/5.0.0.681 4 dtype: int64
最常用的8个浏览器的水平条形图代码:
res_cnt=results.value_counts()[:8] res_cnt.plot(kind='barh',rot=0) plt.show()
然后,我们继续看一下里面的“a”字段,按windows和非windows用户对时区统计信息进行分析
from pandas import DataFrame,Series from matplotlib import pyplot as plt import json path = 'ch02/usagov_bitly_data2012-03-16-1331923249.txt' records = [json.loads(line) for line in open(path)] frame=DataFrame(records) cframe=frame[frame.a.notnull()] # print(cframe.groupby('tz').size()) 发现tz分组后,有521类 operating_system=np.where(cframe['a'].str.contains('Windows'),'Windows','Not Windows') cframe['a']=DataFrame(operating_system) by_tz_os=cframe.groupby(['tz','a']) agg_counts=by_tz_os.size().unstack().fillna(0) #用unstack将行转换成列 print(agg_counts[:10])
输出结果:
a Not Windows Windows tz 180.0 316.0 Africa/Cairo 1.0 2.0 Africa/Casablanca 0.0 1.0 Africa/Ceuta 1.0 1.0 Africa/Johannesburg 0.0 1.0 Africa/Lusaka 1.0 0.0 America/Anchorage 0.0 4.0 America/Argentina/Buenos_Aires 0.0 1.0 America/Argentina/Cordoba 1.0 0.0 America/Argentina/Mendoza 0.0 1.0
最后,接着刚才的操作我们选出最常出现的时区,代码如下:
#用于按升序排列 indexer = agg_counts.sum(1).argsort() #通过take按照这个顺序截取了最后10行 count_subset = agg_counts.take(indexer)[-10:] print(count_subset)
输出结果:
a Not Windows Windows tz America/Sao_Paulo 12.0 21.0 Europe/Madrid 15.0 19.0 Pacific/Honolulu 10.0 25.0 Asia/Tokyo 14.0 23.0 Europe/London 32.0 40.0 America/Denver 56.0 125.0 America/Los_Angeles 122.0 247.0 America/Chicago 131.0 249.0 180.0 316.0 America/New_York 426.0 798.0
用堆积条形图表示:
count_subset.plot(kind='barh',stacked=True) plt.show()