实现数据的高效二进制格式存储最简单的方法之一是使用Python内置的pickle序列化。pandas对象都有一个用于将数据以pickle格式保存到磁盘的to_pickle方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import pandas as pd

frame = pd.read_csv("examples/ex1.csv")
print(frame)

print("转化为二进制格式存储")
frame.to_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直接读取被pickle化的数据,或是使用更为的方便的pandas.read_pickle:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
···
print("读取pickle文件")
result = pd.read_pickle("examples/frame_pickle")
print(result)

# 结果
a b c d message
0 1 2 3 4 hello
1 5 6 7 8 world
2 9 10 11 12 foo
转化为二进制格式存储
读取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仅建议用于短期存储格式。其原因是很难保证该格式永远是稳定的;今天pickle的对象可能无法被后续版本的库unpickle出来。

pandas内置支持两个二进制数据格式:HDF5和MessagePack。

pandas或NumPy数据的其它存储格式有:

  • bcolz:一种可压缩的列存储二进制格式,基于Blosc压缩库。
  • Feather:我与R语言社区的Hadley Wickham设计的一种跨语言的列存储文件格式。Feather使用了Apache Arrow的列式内存格式。

一、使用HDF5格式

HDF5是一种存储大规模科学数组数据的非常好的文件格式。它可以被作为C标准库,带有许多语言的接口,如Java、Python和MATLAB等。HDF5中的HDF指的是层次型数据格式(hierarchical data format)。每个HDF5文件都含有一个文件系统式的节点结构,它使你能够存储多个数据集并支持元数据。与其他简单格式相比,HDF5支持多种压缩器的即时压缩,还能更高效地存储重复模式数据。对于那些非常大的无法直接放入内存的数据集,HDF5就是不错的选择,因为它可以高效地分块读写。

虽然可以用PyTables或h5py库直接访问HDF5文件,pandas提供了更为高级的接口,可以简化存储Series和DataFrame对象。HDFStore类可以像字典一样,处理低级的细节:

1
2
3
4
5
6
7
8
9
10
11
12
import pandas as pd
import numpy as np
frame = pd.DataFrame({"a": np.random.randn(100)})
store = pd.HDFStore("mydata.h5")
store["obj1"] = frame
store["obj1_col"] = frame["a"]

print(store)

# 结果
<class 'pandas.io.pytables.HDFStore'>
File path: mydata.h5

对于HDF5文件中的对象可以通过与字典一样的API进行获取:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
···
print(store["obj1"])
print(store["obj1_col])

# 结果
a
0 1.508136
1 1.371490
2 -0.678362
3 -0.115898
4 -0.411707
.. ...
95 -0.907743
96 2.494934
97 0.083245
98 -0.726677
99 1.818153

[100 rows x 1 columns]
0 1.508136
1 1.371490
2 -0.678362
3 -0.115898
4 -0.411707
...
95 -0.907743
96 2.494934
97 0.083245
98 -0.726677
99 1.818153
Name: a, Length: 100, dtype: float64

HDFStore支持两种存储模式,’fixed’和’table’。后者通常会更慢,但是支持使用特殊语法进行查询操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
···
print("-----")
store.put("obj2", frame, format="table")
print(store.select("obj2", where=['index >= 10 and index <= 15']))
store.close()
# 结果
a
10 -1.734418
11 1.074554
12 -0.212570
13 -0.458444
14 -0.568209
15 -0.249405

put是store[‘obj2’] = frame方法的显示版本,允许我们设置其它的选项,比如格式。

pandas.read_hdf函数可以快捷使用这些工具:

1
2
3
4
5
6
7
8
9
10
11
···
frame.to_hdf("mydata.h5", "obj3", format="table")
print(pd.read_hdf("mydata.h5", "obj3", where=["index<5"]))

# 结果
a
0 -0.814172
1 1.085430
2 0.751443
3 0.355575
4 0.244581

由于许多数据分析问题都是IO密集型(而不是CPU密集型),利用HDF5这样的工具能显著提升应用程序的效率。

注意:HDF5不是数据库。它最适合用作“一次写多次读”的数据集。虽然数据可以在任何时候被添加到文件中,但如果同时发生多个写操作,文件就可能会被破坏。

二、读取Microsoft Excel文件

pandas的ExcelFile类或pandas.read_excel函数支持读取存储在Excel 2003(或更高版本)中的表格型数据。这两个工具分别使用扩展包xlrd和openpyxl读取XLSXLSX文件。

要使用ExcelFile,通过传递xls或xlsx路径创建一个实例:

1
2
3
4
5
6
7
import pandas as pd

xlsx = pd.ExcelFile("examples/ex1.xlsx")
print(xlsx)

# 结果
<pandas.io.excel._base.ExcelFile object at 0x00000167778BD550>

储在表单中的数据可以read_excel读取到DataFrame:

1
2
3
4
5
6
7
8
result = pd.read_excel(xlsx)
print(result)

# 结果
Unnamed: 0 a b c d message
0 0 1 2 3 4 hello
1 1 5 6 7 8 world
2 2 9 10 11 12 foo

果要读取一个文件中的多个表单,创建ExcelFile会更快,但你也可以将文件名传递到pandas.read_excel:

1
2
3
4
5
6
7
8
frame = pd.read_excel("examples/ex1.xlsx", "Sheet1")
print(frame)

# 结果
Unnamed: 0 a b c d message
0 0 1 2 3 4 hello
1 1 5 6 7 8 world
2 2 9 10 11 12 foo

如果要将pandas数据写入为Excel格式,你必须首先创建一个ExcelWriter,然后使用pandas对象的to_excel方法将数据写入到其中:

1
2
3
writer = pd.ExcelWriter("examples/ex2.xlsx")
frame.to_excel(writer, "Sheet1")
writer._save()

你还可以不使用ExcelWriter,而是传递文件的路径到to_excel:

1
frame.to_excel('examples/ex2.xlsx')