利用python进行数据分析之数据加载、存储与文件格式

书中源码与数据集http://github.com/pydata/pydata-book

目录

6.1 读写文件格式的数据

6.2 二进制数据格式

6.3 使用 html 和web API

6.4 使用数据库

输入和输出可以划分几个大类:读取文本文件和其他更高效的磁盘存储格式,加载数据库中的数据,利用web API操作网络资源。

6.1 读写文件格式的数据

pandas中得解析函数

函数

read_csv       从文件、URL、文件型对象中加载带分隔符的数据。默认分隔符为逗号

read_table    从文件、URL、文件型对象中加载带分隔符的数据。默认分隔符为制表符("\t")

reda_fwf       读取定宽格式数据(没有分隔符)

read_clipboard  读取剪贴板中的数据,可以看做read_table的剪贴板版。在将网页转换为表格时很有用

这些函数的选项可以划分下面几大类:

索引:将一个或多个列当做返回的DataFrame处理,以及是否从文件、用户获得列名

类型推断和数据转换:包括用户定义值得转换、缺失值标记列表等

日期解析:包括组合功能,比如将分散在多个列中的日期时间信息组合成结果中的单个列。

迭代:支持对大文件进行逐块迭代

不规整数据问题:跳过一些行、页脚、注释或其他一些不重要的东西(比如成千上万个逗号隔开的数值数据)

类型推断是这些函数中最重要的功能之一。我们不需要知道列的类型到底是数值、整数、布尔值、还是字符串。

我们给出一个以逗号分隔的(CSV)文件:

我们使用type的这个Window shell命令将文本的原始内容打印到屏幕上。

In [22]:!type E:\\ch06ex1.csv

a,b,c,d,message

1,2,3,4,hello

5,6,7,8,world

9,10,11,12,foo

由于文件以逗号分隔,所以我们可以使用read_csv将其读入一个DataFrame:

In [25]:df=pd.read_csv('E:\\ch06ex1.csv')

In [26]:df

Out[26]:

a b c d message

0 1 2 3 4 hello

1 5 6 7 8 world

2 9 10 11 12 foo

还可以使用read_table ,这时需要指定分隔符:

In [28]:pd.read_table('E:\\ch06ex1.csv',sep=',')

Out[28]:

a b c d message

0 1 2 3 4 hello

1 5 6 7 8 world

2 9 10 11 12 foo

假如不指定分隔符:

In [29]:pd.read_table('E:\\ch06ex1.csv')

Out[29]:

a,b,c,d,message

0 1,2,3,4,hello

1 5,6,7,8,world

2 9,10,11,12,foo

并不是所有的文件本身就有标题行。我们可以自己分配默认的列名,也可以自己定义列名:

In [3]:!type E:\\ch06ex2.csv

1,2,3,4,hello

5,6,7,8,world

9,10,11,12,foo

In [5]:pd.read_csv('E:\\ch06ex2.csv',header=None)

Out[5]:

0 1 2 3 4

0 1 2 3 4 hello

1 5 6 7 8 world

2 9 10 11 12 foo

In [8]:pd.read_csv('E:\\ch06ex2.csv',names=['a','b','c','d','message'])

Out[8]:

a b c d message

0 1 2 3 4 hello

1 5 6 7 8 world

2 9 10 11 12 foo

假如我们希望将message列作为DataFrame的索引,我们可以明确表示要将该列放在索引4的位置上,也可以通过index_col参数指定“message” :

In [10]:names=['a','b','c','d','message']

In [11]:pd.read_csv('E:\\ch06ex2.csv',names=names,index_col='message')

Out[11]:

a b c d

message

hello 1 2 3 4

world 5 6 7 8

foo 9 10 11 12

如果我们希望将多个列做成一个层次化索引,只需要传入编号或列名组成的列表即可:

In [15]:!type E:\\ch06_mindex.csv

key1,key2,value1,value2

one,a,1,2

one,b,3,4

one,c,5,6

one,d,7,8

two,a,9,10

two,b,11,12

two,c,13,14

two,d,15,16

In [17]:parsed=pd.read_csv('E:\\ch06_mindex.csv',index_col=['key1','key2'])

In [18]:parsed

Out[18]:

value1 value2

key1 key2

one a 1 2

b 3 4

c 5 6

d 7 8

two a 9 10

b 11 12

c 13 14

d 15 16

有些表格可能不是用固定的分隔符去分隔字段的,对于这种情况,我们编写一个正则表达式来作为 read_table的分隔符。

In [35]:list(open('E:\\ch06ex3.txt'))

Out[35]:

[' A B C\n',

'aaa -0.264438 -1.343465 -0.619500\n',

'bbb -0.264438 -1.343465 -0.619500\n',

'ccc -0.264438 -1.343465 -0.619500\n',

'ddd -0.264438 -1.343465 -0.619500\n']

该文件各个字段由数量不定的空白字符分隔。我们可以使用正则表达式\s+ 表示,

In [36]:result=pd.read_table('E:\\ch06ex3.txt',sep='\s+')

In [37]:result

Out[37]:

A B C

aaa -0.264438 -1.343465 -0.6195

bbb -0.264438 -1.343465 -0.6195

ccc  -0.264438 -1.343465 -0.6195

ddd  -0.264438 -1.343465 -0.6195

上面由于列名比数据行的数量少,索引read_table推断第一列应该是DataFrame的索引。

许多解析器函数的许多参数可以帮助你处理各种各样的异形文件格式。比如,用skiprows跳过文件的第一行、第三行、第四行。

In [4]:!type E:\\ch06ex4.csv

#hey!

a,b,c,d,message

#just wanted to make things more difficult for you

#who reads CSV files with computers,anyway?

1,2,3,4,hello

5,6,7,8,world

9,10,11,12,foo

In [5]:pd.read_csv('E:\\ch06ex4.csv',skiprows=[0,2,3])

Out[5]:

a b c d message

0 1 2 3 4 hello

1 5 6 7 8 world

2 9 10 11 12 foo

缺失值处理是文件解析任务重要组成。缺失数据会没有空字符串,或者某个标记值表示。

默认下,pandas会用一组常出现的标记值进行识别,如NA,-1.#IND以及NULL等:

In [56]:!type E:\\ch06ex5.csv

something,a,b,c,d,message

one,1,2,3,4,NA

two,5,6,,8,world

three,9,10,11,12,foo

In [58]:import pandas as pd

In [59]:result=pd.read_csv('E:\\ch06ex5.csv')

In [60]:result

Out[60]:

something a b c d message

0 one 1 2 3.0 4 NaN

1 two 5 6 NaN 8 world

2 three 9 10 11.0 12 foo

In [61]:pd.isnull(result)

Out[61]:

something a b c d message

0 False False False False False True

1 False False False True False False

2 False False False False False False

na_values可以接受一组用于表示缺失值的字符串:

In [62]:result=pd.read_csv('E:\\ch06ex5.csv',na_values=['NULL'])

In [63]:result

Out[63]:

something a b c d message

0 one 1 2 3.0 4 NaN

1 two 5 6 NaN 8 world

2 three 9 10 11.0 12 foo

可以用一个字典为各列指定不同的NA标记值:

In [65]:sentinels={'message':['foo','NA'],'something':['two']}

In [66]:result=pd.read_csv('E:\\ch06ex5.csv',na_values=sentinels)

In [67]:result

Out[67]:

something a b c d message

0 one 1 2 3.0 4 NaN

1 NaN 5 6 NaN 8 world

2 three 9 10 11.0 12 NaN

6.1 .1 逐块读取文件文件

处理大文件时候,我们可能需要文件的一小部分,或者逐块对文件进行迭代:

In [4]: result=pd.read_csv(r'F:\pydata-book-master\ch06\ex6.csv')

In [5]: result

Out[5]:

one      two    three      four key

00.467976-0.038649-0.295344-1.824726L

1    -0.3588931.4044530.704965-0.200638B

2    -0.5018400.659254-0.421691-0.057688G

30.2048861.0741341.388361-0.982404R

40.354628-0.1331160.283763-0.837063Q

51.8174800.7422730.419395-2.251035Q

...        ...      ...      ...      ...  ..

99931.8211170.4164450.1738740.505118X

99940.0688041.3227590.8023460.223618H

99952.311896-0.417070-1.409599-0.515821L

9996 -0.479893-0.6504190.745152-0.646038E

99970.5233310.7871120.4860661.093156K

9998 -0.3625590.598894-1.8432010.887292G

9999 -0.096376-1.012999-0.657431-0.5733150

[10000 rows x 5 columns]

我们只想读取几行的,通过nrows来指定行即可:

In [7]: pd.read_csv(r'F:\pydata-book-master\ch06\ex6.csv',nrows=5)

Out[7]:

one      two    three      four key

00.467976-0.038649-0.295344-1.824726L

1 -0.3588931.4044530.704965-0.200638B

2 -0.5018400.659254-0.421691-0.057688G

30.2048861.0741341.388361-0.982404R

40.354628-0.1331160.283763-0.837063Q

要逐块读取文件,需要设置chunksize (行数):

In [10]:chunker=pd.read_csv(r'F:\pydata-book-master\ch06\ex6.csv',chunksize=10000)

In [11]:chunker

Out[11]:

read_csv所返回的这个TextParser对象使你可以根据chunksize对文件进行逐块迭代。

比如我们可以迭代ex6.csv,将值计数聚合到“key”中,

In [10]:chunker=pd.read_csv(r'F:\pydata-book-master\ch06\ex6.csv',chunksize=10000)

In [11]:chunker

Out[11]:

In [13]:from pandas import Series,DataFrame

In [14]:tot=Series([])

In [15]:for piece in chunker:

...:tot=tot.add(piece['key'].value_counts(),fill_value=0)

...:

In [16]:tot.order(ascending=False)

__main__:1: FutureWarning: order is deprecated, use sort_values(...)

Out[16]:

E 368.0

X 364.0

L 346.0

O 343.0

Q 340.0

M 338.0

J 337.0

F 335.0

K 334.0

H 330.0

V 328.0

I 327.0

U 326.0

P 324.0

D 320.0

A 320.0

R 318.0

Y 314.0

G 308.0

S 308.0

N 306.0

W 305.0

T 304.0

B 302.0

Z 288.0

C 286.0

4 171.0

6 166.0

7 164.0

3 162.0

8 162.0

5 157.0

2 152.0

0 151.0

9 150.0

1 146.0

dtype: float64

In [17]:tot[:6]

Out[17]:

E 368.0

X 364.0

L 346.0

O 343.0

Q 340.0

M 338.0

dtype: float64

6.1.2 将数据写出到文本格式

将数据写出带文本格式

数据也可以被输出为分隔符个格式的文本。

我们看看之前读过的CSV文件。

In [1]: import pandas as pd

In [2]: data=pd.read_csv(r"F:\pydata-book-master\ch06\ex5.csv")

In [3]: data

Out[3]:

something  a  b    c  d message

0      one  1  2  3.0  4    NaN

1      two  5  6  NaN  8  world

2    three  9  10  11.0  12    foo

In [6]: !type "F:\pydata-book-master\ch06\out.csv"

,something,a,b,c,d,message

0,one,1,2,3.0,4,

1,two,5,6,,8,world

2,three,9,10,11.0,12,foo

当然,还可以使用其他分隔符

In [8]: import sys

In [9]: data.to_csv(sys.stdout,sep='|')

|something|a|b|c|d|message

0|one|1|2|3.0|4|

1|two|5|6||8|world

2|three|9|10|11.0|12|foo

缺失值在输出结果中会被表示为空字符,可能我们会希望将它表示其他字符

In [10]: data.to_csv(sys.stdout,na_rep="NULL")

,something,a,b,c,d,message

0,one,1,2,3.0,4,NULL

1,two,5,6,NULL,8,world

2,three,9,10,11.0,12,foo

没有其他选项会写出行和列标签。

In [11]: data.to_csv(sys.stdout,index=False,header=False)

one,1,2,3.0,4,

two,5,6,,8,world

three,9,10,11.0,12,foo

还可以写出一部分列,指定以下的顺序排列:

Series有一个to_csv的方法,

In [16]: from pandas import Series,DataFrame

In [18]: import numpy as np

In [20]: dates=pd.date_range('1/1/2000',periods=7)

In [21]: ts=Series(np.arange(7),index=dates)

In [22]: ts.to_csv(r"F:\pydata-book-master\ch06\tseries.csv")

In [23]: !type F:\pydata-book-master\ch06\tseries.csv"

2000-01-01,0

2000-01-02,1

2000-01-03,2

2000-01-04,3

2000-01-05,4

2000-01-06,5

2000-01-07,6

我们还有一个from_csv方法:

In [24]: Series.from_csv(r'F:\pydata-book-master\ch06\tseries.csv',parse_dates=True)

Out[24]:

2000-01-01    0

2000-01-02    1

2000-01-03    2

2000-01-04    3

2000-01-05    4

2000-01-06    5

2000-01-07    6

dtype: int64

6.1.3 ·手工处理分隔符格式

大部分表格型数据用到pandas.read_table进行加载。有时候我们需要一些手工处理。

In [25]: !type F:\pydata-book-master\ch06\ex7.csv

"a","b","c"

"1","2","3"

"1","2","3","4"

对于单字符分隔符文件,可以直接使用python内置的csv模块。将任意的打开的文件或文件型的对象传给csv.reader

In [26]: import csv

In [27]: f=open(r"F:\pydata-book-master\ch06\ex7.csv")

In [28]: reader=csv.reader(f)

#对这个reader进行迭代将会为每行产生一个元组:

In [30]: for line in reader:

...:    print line

...:

['a', 'b', 'c']

['1', '2', '3']

['1', '2', '3', '4']

为了使数据格式合乎要求,需要我们整理一下:

In [4]:lines=list(csv.reader(open('F:\pydata-book-master\ch06\ex7.csv')))

In [5]:header,values=lines[0],lines[1:]

In [8]:header,values

Out[8]:(['a', 'b', 'c'], [['1', '2', '3'], ['1', '2', '3', '4']])

In [9]:data_dict={h:v for h,v in zip(header,zip(*values))}

In [10]:header,values

Out[10]:(['a', 'b', 'c'], [['1', '2', '3'], ['1', '2', '3', '4']])

csv文件的形式有很多种,只需要定义csv.Dialect的一个子类可定义出新格式(如专门的分隔符、字符串引用约定、行结束符等):

In [22]:class my_dialect(csv.Dialect):

...:lineterminator='\n'

...:delimiter=';'

...:quotechar='"'

...:

In [25]:f=open(r"E:\pydata-book-master\pydata-book-master\ch06\ex7.csv")

In [26]:reader = csv.reader(f, dialect=my_dialect, quoting = csv.QUOTE_ALL)

In [27]:reader

Out[27]:<_csv.reader at 0x245b0168>

各个csv语支的参数可以关键字的形式提供给csv.reader ,而无需定义子类:

reader=csv.reader(f,delimiter='|')

注意:对于复杂的分隔符或多字符的分隔符的文件,我们要使用字符串的split方法或正则表达式re.split进行拆分和其他整理工作。

我们在手动的输出分隔符的文件,可以使用csv.writer

它接收一个已经打开的且可写的文件对象以及跟csv.reader相同的那些语支和格式化选项:

In [30]:with open(r'E:\pydata-book-master\pydata-book-master\ch06\mydata.csv','w') as f:

...:writer=csv.writer(f,dialect=my_dialect,quoting = csv.QUOTE_ALL)

...:writer.writerow(('one','two','three'))

...:writer.writerow(('1','2','3'))

...:writer.writerow(('4','5','6'))

...:writer.writerow(('7','8','9'))

6.1.4 JSON数据

JSON(JavaScript Object Notation的简称)已经成为通过HTTP请求在Web浏览器和其他应用程序之间发送数据的标准格式之一。

JSON是一种比表格型文本格式(如CSV)灵活得多的数据格式:

json的本质是字典,是hash表,用来存储非结构化的数据。

csv本质是表,用来存储结构化数据

给出一个例子

obj="""{"name":"Wes","places_lived":["United States","Spain","Germany"],"pet":null,"siblings":[{"name":"Scott","age":25,"pet":"Zuko"},{"name":"Katie","age":33,"pet":"Cisco"}]}"""

In [12]:obj="""{"name":"Wes","places_lived":["United States","Spain","Germany"],"pet":null,"siblings":[{"name":"Scott","age":25,"pet":"Zuko"},{"name":"Katie","age":33,"pet":"Cisco"}]}"""

JSON非常接近有效的python代码。基本类型有对象(字典),数组(列表),字符串,数值,布尔值,以及null。

对象中的键必须是字符串。

In [13]:import json

In [14]:result=json.loads(obj)

In [15]:result

Out[15]:

{'name': 'Wes',

'pet': None,

'places_lived': ['United States', 'Spain', 'Germany'],

'siblings': [{'age': 25, 'name': 'Scott', 'pet': 'Zuko'},

{'age': 33, 'name': 'Katie', 'pet': 'Cisco'}]}

相反,json.dump则将python对象转换为JSON格式:

asjson=json.dumps(result)

如何将JSON对象转换为DataFrame 或其他便于分析的数据结构。

最为方便的一个方式:向DataFrame构造器传入一组JSON对象,并选取数据字段的子集。

In [29]:siblings=DataFrame(result['siblings'],columns=['name','age'])

In [30]:siblings

Out[30]:

name age

0 Scott 25

1 Katie 33

6.1.5 XML和HTML:Web信息收集

python中有许多可以读写HTML和XML格式数据的库,lxml就是其中之一,它能够高效的解析大文件。lxml有多编程接口,首先要要用lxml.html处理HTML,然后在用lxml.objetify做一些XML处理。

In [31]:from lxml.html import parse

In [32]:from urllib2 import urlopen

In [33]:parsed=parse(urlopen=('http://finance.yahoo.com/q/op?s=AAPL+Options'))

Traceback(most recent call last):

File"", line1, in

parsed=parse(urlopen=('http://finance.yahoo.com/q/op?s=AAPL+Options'))

TypeError:parse() takes at least 1 argument (0 given)

6.1.5.1 利用lxml.objectify 解析XML

XML(extensible markup language)是另一种常见的支持分层、嵌套数据以及元数据的结构化数据格式。

6.2 二进制数据格式

实现数据的二进制格式的存储的最简单的办法之一就是使用python内置的pickle序列化。为了使用方便,pandas 对象都有一个将数据以pickle形式保存到磁盘上的save的方法;

6.3 使用 html 和web API

6.4 使用数据库

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,968评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,601评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,220评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,416评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,425评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,144评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,432评论 3 401
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,088评论 0 261
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,586评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,028评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,137评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,783评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,343评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,333评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,559评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,595评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,901评论 2 345

推荐阅读更多精彩内容