数据分析第一章

知识点:序列化和反序列化

1.使用'w'写入的数据只能是字符串或者二进制,否则会报错

info = {'name':'buyang', 'age':28}
fr = open('test.txt', 'w')
fr.write(info)
TypeError: write() argument must be str, not dict

稍作修改:

info = {'name':'buyang', 'age':28}
fr = open('test.txt', 'w')
fr.write(str(info))

文本中的内容为:{'name': 'buyang', 'age': 28}

如果此时想将写入的内容恢复过来,恢复是指恢复成字典,我们使用

fr = open('test.txt', 'r')
data = fr.read()

只能得到字符串:{'name': 'buyang', 'age': 28},此时并不是字典,此时需要用到序列化和反序列化:

写入的时候是这样操作:

import json
info = {'name': 'buyang', 'age': 28}
f = open('test.txt', 'w')
f.write( json.dumps(info) )  #json.dumps(info)将info的指向内容变为字符串

读的时候:

import json
fr = open('test.txt', 'r')
data = json.loads(fr.read())
print(data)
print(data['name'])  #   结果:{'name': 'buyang', 'age': 28}   buyang, 表明读出的是字典

json只能处理简单的数据类型,如字符串,列表,字典等,另外一个模块pickle可以处理更多种类类型,由于并未用到pickle的相关知识,所有此处不多做介绍。

书上代码:

path = 'E:\数据分析代码数据\pydata-book-2nd-edition\datasets\\bitly_usagov\example.txt'

\\bitly_usagov,两个\\中前一个转义,防止出现\b

for line in open(path): #open(path)是iteration对象,可以直接读出文本中的每个字典
    print(line)

所以可以使用一个列表生成式:

import json
path = 'E:\数据分析代码数据\pydata-book-2nd-edition\datasets\\bitly_usagov\example.txt'
records = [json.loads(line) for line in open(path)]
print(records[0])  #读出来的是列表而不是str,可以进行records[0]['tz']的操作

提取每个字典中的时区信息:

import json
path = 'E:\数据分析代码数据\pydata-book-2nd-edition\datasets\\bitly_usagov\example.txt'
records = [json.loads(line) for line in open(path)]
time_zones = [rec['tz'] for rec in records if 'tz' in rec]
print(time_zones[:10])    #只提取前10个
['America/New_York', 'America/Denver', 'America/New_York', 'America/Sao_Paulo', 'America/New_York', 'America/New_York', 'Europe/Warsaw', '', '', ''],注意到有3个是空的


编写一段对时区计数的函数:

def get_counts(sequence):
    counts = {}
    for x in sequence:
        if x in counts:
            counts[x] += 1
        else:
            counts[x] = 1
    return counts

print(get_counts(time_zones))

排序函数:

def top_counts(count_dict):
    value_key_pairs = [(tz, count) for tz,count in count_dict.items()]
    value_key_pairs_sort = sorted(value_key_pairs, key=lambda x:x[1], reverse=True)
    return value_key_pairs_sort

使用pandas:

import json
from pandas import DataFrame, Series
import pandas as pd
import numpy as np

path = 'E:\数据分析代码数据\pydata-book-2nd-edition\datasets\\bitly_usagov\example.txt'
records = [json.loads(line) for line in open(path)]
frame = DataFrame(records)
print(frame)

frame是<class 'pandas.core.frame.DataFrame'>,共1560行 * 18列

print(frame['tz'][:10])

显示frame中'tz'这个特征列的前10个数据,结果为:

0     America/New_York

1       America/Denver

2     America/New_York

3    America/Sao_Paulo

4     America/New_York

5     America/New_York

6        Europe/Warsaw

7                     

8                     

9                     

发现在'tz'特征列前10个数中有3个值是空白,稍后将进行填补空白

tz_counts = frame['tz'].value_counts()
print(tz_counts[:10])

这里的.value_counts()的功能是按 'tz' 特征的特征值出现次数进行降序排序,暂时还未用到其他改变函数参数的功能

接下来是填补空缺,有两种空缺,第一种是 'tz':'',即tz特征下是空白,第二种更过分,直接没有'tz'这个特征(关键字),两种空缺的填补方式如下:

#用'Missing'替代缺失值,缺失值指的是有120个字典数据中没有'tz'这个关键字
#填补后从没有'tz'关键字变为 'tz':'Missing'
clean_tz = frame['tz'].fillna('Missing')
#用'Unknown'替代'tz'关键字下为的空白,如'tz':''变为'tz':'Unknown'
clean_tz[clean_tz == ''] = 'Unknown'

clean_tz是在frame['tz']的基础上生成的,第一步之后clean_tz是填补了第二种缺失值之后的'tz'特征下的特征值全体,接下来开始在此基础上填补第一种缺失值。如果不填补第二种缺失值,可以写成:

frame['tz'][frame['tz'] == ''] = 'Unknown'
print(frame['tz'][:10])

0     America/New_York
1       America/Denver
2     America/New_York
3    America/Sao_Paulo
4     America/New_York
5     America/New_York
6        Europe/Warsaw
7              Unknown
8              Unknown
9              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          #120个字典没有关键字'tz'
Europe/London            74
Asia/Tokyo               37
Pacific/Honolulu         36

Europe/Madrid            35

还可以直接使用tz_counts[:10]作为对象进行绘图

需要 from pylab import *

tz_counts[:10].plot(kind='barh',rot=0)
show()     #在pycharm中必须要show()才能显示绘图



print(frame.tz[:10])
print(frame['tz'][:10])
这两条语句的意思相同


def dropna(self, axis=0, how='any', thresh=None, subset=None,inplace=False)

具体解释见:http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.dropna.html

print(frame.a[:5])
0    Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKi...
1                               GoogleMaps/RochesterNY
2    Mozilla/4.0 (compatible; MSIE 8.0; Windows NT ...
3    Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8)...

4    Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKi...

frame.a.dropna()

去除a特征中所有特征值中NaN的值

print( [x.split()[0] for x in frame.a[:5].dropna()] )

['Mozilla/5.0', 'GoogleMaps/RochesterNY', 'Mozilla/4.0', 'Mozilla/5.0', 'Mozilla/5.0']

Series函数:https://www.cnblogs.com/linux-wangkun/p/5903380.html

results = Series( [x.split()[0] for x in frame.a.dropna()] )  #去除了NaN
print(results[:5])
0               Mozilla/5.0
1    GoogleMaps/RochesterNY
2               Mozilla/4.0
3               Mozilla/5.0
4               Mozilla/5.0



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

print(frame.a[:20].notnull())
0      True
1      True
2      True
3      True
4      True
5      True
6      True
7      True
8      True
9      True
10     True
11     True
12     True
13    False      #序号13的数据本来是NaN,所以显示False
14     True
15     True
16     True
17     True
18     True

19     True

用此方法去除没有'a'特征的数据(有特征但没有数据会显示空白,没有该特征只会显示NaN)

frame[frame.a.notnull()]

然后根据a特征的值来分辨各行是否是Windows

operating_system = np.where( cframe['a'].str.contains('Windows'), 'Windows', 'Not Windows' )

由Numpy中的where函数实现,按照a特征中的特征值中的字符串中是否含有'Windows'分为'Windows'和'Not Windows'两类

print( operating_system[:5] )

返回:['Windows' 'Not Windows' 'Windows' 'Not Windows' 'Windows'],数据类型是<class 'numpy.ndarray'>

接下来根据时区和新的到的操作系统列表对数据进行分组:

by_tz_os = cframe.groupby( ['tz', operating_system] )

然后使用size()进行计数,用unstack()对计数结果进行重塑:

def unstack(self, level=-1, fill_value=None)

关于unstack的介绍:http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.unstack.html

并将NaN位置替换为数值0

agg_counts = by_tz_os.size().unstack().fillna(0)

 前10个数据

                                                        Not Windows  Windows

tz                                                  
                                                          245.0    276.0
Africa/Cairo                                         0.0      3.0
Africa/Casablanca                                0.0      1.0
Africa/Ceuta                                        0.0      2.0
Africa/Johannesburg                            0.0      1.0
Africa/Lusaka                                       0.0      1.0
America/Anchorage                             4.0      1.0
America/Argentina/Buenos_Aires         1.0      0.0
America/Argentina/Cordoba                0.0      1.0

America/Argentina/Mendoza               0.0      1.0

第一行表示的是本身没有tz特征的特征值的所有数据中(没有地区信息的所有数据),Not Windows  和 Windows的数量

这些知识都在下列章节有详细讲解,此处不做过多介绍。







阅读更多 登录后自动展开
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页