最简单的以二进制的格式来存储数据的方法(也被叫做serialization
,序列化),就是用python
内建的pickle
。所有的pandas object
都有一个to_pickle
方法,可以用来存储数据为pickle
格式:
import pandas as pd
import numpy as np
frame = pd.read_csv('../examples/ex1.csv')
frame
a | b | c | d | message | |
---|---|---|---|---|---|
0 | 1 | 2 | 3 | 4 | hello |
1 | 5 | 6 | 7 | 8 | world |
2 | 9 | 10 | 11 | 12 | foo |
frame.to_pickle('../examples/frame_pickle')
!ls ../examples/
array_archive.npz [31mmacrodata.csv[m[m
array_compressed.npz mydata.csv
[31marray_ex.txt[m[m [31mout.csv[m[m
[31mcsv_mindex.csv[m[m [31msegismundo.txt[m[m
[31mex1.csv[m[m sink.txt
[31mex1.xlsx[m[m some_array.npy
[31mex2.csv[m[m [31mspx.csv[m[m
[31mex3.csv[m[m [31mstinkbug.png[m[m
[31mex3.txt[m[m [31mstock_px.csv[m[m
[31mex4.csv[m[m [31mstock_px_2.csv[m[m
[31mex5.csv[m[m [31mtest_file.csv[m[m
[31mex6.csv[m[m [31mtips.csv[m[m
[31mex7.csv[m[m tmp.txt
[31mexample.json[m[m [31mtseries.csv[m[m
[31mfdic_failed_bank_list.html[m[m [31mvolume.csv[m[m
frame_pickle [31myahoo_price.pkl[m[m
[31mipython_bug.py[m[m [31myahoo_volume.pkl[m[m
用内建的pickle
可以直接读取任何pickle
文件,或者直接用pandas.read_pickle
:
pd.read_pickle('../examples/frame_pickle')
a | b | c | d | message | |
---|---|---|---|---|---|
0 | 1 | 2 | 3 | 4 | hello |
1 | 5 | 6 | 7 | 8 | world |
2 | 9 | 10 | 11 | 12 | foo |
注意:pickle
只推荐用于短期存储。因为这种格式无法保证长期稳定;比如今天pickled
的一个文件,可能在库文件更新后无法读取。
python
还支持另外两种二进制数据格式:HDF5
和MessagePack
。下面会介绍一个HDF5
,但是我们鼓励你多尝试一个不同的文件格式,看看他们能有多快,是否符合你数据分析的要求。另外一些可用的存储格式有:bcolz
和 Feather
。
HDF5
格式是用来存储大量的科学数组数据的。这种格式还能用于其他一些语言。其中HDF
表示hierarchical data format
。每一个HDF5
格式能春初多个数据集,并支持metadata
。
元数据(meta data)——“data about data” 关于数据的数据,一般是结构化数据(如存储在数据库里的数据,规定了字段的长度、类型等)。元数据是指从信息资源中抽取出来的用于说明其特征、内容的结构化的数据(如题名,版本、出版数据、相关说明,包括检索点等),用于组织、描述、检索、保存、管理信息和知识资源。
HDF5
支持多种压缩模式的on-the-fly compression
(即时压缩),能让数据中一些重复的部分存储地更有效。HDF5
对于处理大数据集是一个很好的选择,因为他不会把所有数据一次性读取到内存里,我们可以从很大的数组中有效率地读取一小部分。
能用PyTables
或h5py
来访问HDF5
数据,pandas
也有提供一个high-level
的交互界面。HDFStore
类像dict
一样能用来处理low-level
细节:
frame = pd.DataFrame({'a': np.random.randn(100)})
store = pd.HDFStore('../examples/mydata.h5')
frame.head()
a | |
---|---|
0 | 0.908968 |
1 | -0.589368 |
2 | 0.015493 |
3 | 0.029850 |
4 | 1.682180 |
cat ../examples/mydata.csv
one;two;three
1;2;3
4;5;6
7;8;9
store['obj1'] = frame
store['obj1_col'] = frame['a']
store
File path: ../examples/mydata.h5
/obj1 frame (shape->[100,1])
/obj1_col series (shape->[100])
HDF5
中的object
能用像dict
一样的API
来提取:
store['obj1']
a | |
---|---|
0 | 0.908968 |
1 | -0.589368 |
2 | 0.015493 |
3 | 0.029850 |
4 | 1.682180 |
5 | -0.977549 |
6 | 0.806008 |
7 | -0.458852 |
8 | -0.833007 |
9 | 0.410430 |
10 | -0.232093 |
11 | 0.002657 |
12 | -0.642136 |
13 | -1.772356 |
14 | 0.411567 |
15 | 1.259846 |
16 | -0.730757 |
17 | -1.401318 |
18 | 2.984850 |
19 | -0.140144 |
20 | -0.972235 |
21 | -0.592930 |
22 | 1.538674 |
23 | -0.052034 |
24 | 0.260698 |
25 | -0.859609 |
26 | 1.119075 |
27 | -0.898982 |
28 | 0.191869 |
29 | 1.013184 |
... | ... |
70 | 0.507719 |
71 | -0.146967 |
72 | 0.694807 |
73 | -0.482966 |
74 | 1.816455 |
75 | 0.535113 |
76 | -1.006997 |
77 | 2.088429 |
78 | -0.449548 |
79 | 1.133784 |
80 | 0.413018 |
81 | 0.324538 |
82 | 1.434230 |
83 | 0.767194 |
84 | 2.073305 |
85 | -2.643750 |
86 | 2.330771 |
87 | -1.683786 |
88 | 1.631209 |
89 | 0.036383 |
90 | 0.755447 |
91 | -0.712269 |
92 | -0.914963 |
93 | -0.660928 |
94 | 1.465104 |
95 | 0.101968 |
96 | 0.669502 |
97 | -0.210062 |
98 | -0.453599 |
99 | 0.848008 |
100 rows × 1 columns
HDFStore
支持两种存储架构,fixed
和table
。后者通常更慢一些,但支持查询操作:
store.put('obj2', frame, format='table')
store.select('obj2', where=['index >= 10 and index <= 15'])
a | |
---|---|
10 | -1.186667 |
11 | 0.628998 |
12 | -0.668921 |
13 | 0.775731 |
14 | -1.329899 |
15 | 1.920832 |
put
是存储的另一种写法,类似于之前的store['obj2'] = frame
,但这种协防能让我们设置存储格式。
pandas.read_hdf
函数也很方便:
frame.to_hdf('../examples/mydata.h5', 'obj3', format='table')
pd.read_hdf('../examples/mydata.h5', 'obj3', where=['index < 5'])
a | |
---|---|
0 | 1.324210 |
1 | 0.770813 |
2 | 0.554799 |
3 | -1.741867 |
4 | -1.875071 |
注意:如果我们是把数据存在远端服务器上,比如Amazon S3
或HDFS
,使用一些为分布式存储实际的二进制格式会更适合一些,比如Apache Parquet
。
如果是在本地处理很大数据量的话,推荐尝试PyTables
和h5py
看是否符合你的要求。因为很多数据分析问题都受限于I/O
,所以用HDF5
这样的工具能加快应用。
注意:HDF5
不是数据库(database
)。它最适合一次写入,多次读取的数据库。尽管数据可以在任何时间多次写入一个文件,如果多个使用者同时写入的话,文件会被破坏。
pandas
支持读取表格型数据(excel 2003
或更高)文件,使用ExcelFile class
或pandas.read_excel
函数。这些工具需要一些富家的包xlrd
和openpyxl
来分别读取XLS
和XLSX
文件。你可以通过pip
或conda
来安装。
使用ExcelFile
,创建一个instance
,通过给xls
或xlsx
一个路径:
xlsx = pd.ExcelFile('../examples/ex1.xlsx')
保存在sheet
里的数据,可以通过parse
来读取为DataFrame
:
pd.read_excel(xlsx, 'Sheet1')
a | b | c | d | message | |
---|---|---|---|---|---|
0 | 1 | 2 | 3 | 4 | hello |
1 | 5 | 6 | 7 | 8 | world |
2 | 9 | 10 | 11 | 12 | foo |
如果要读取一个文件中的多个sheet
,用ExcelFile
会更快。但让你也能把文件名直接传递给pandas.read_excel
:
frame = pd.read_excel('../examples/ex1.xlsx', 'Sheet1')
frame
a | b | c | d | message | |
---|---|---|---|---|---|
0 | 1 | 2 | 3 | 4 | hello |
1 | 5 | 6 | 7 | 8 | world |
2 | 9 | 10 | 11 | 12 | foo |
如果要把pandas
数据写为Excel
格式,你必须先创建一个ExcelWrite
,然后用to_excel
方法:
writer = pd.ExcelWriter('../examples/ex2.xlsx')
frame.to_excel(writer, 'Sheet1')
writer.save()
如果不适用ExcelWriter
的话,可以直接传给to_excel
一个path
:
frame.to_excel('../examples/ex2.xlsx')