HDF5比CSV占用更多的空间?

39

考虑以下例子:

准备数据:

import string
import random
import pandas as pd

matrix = np.random.random((100, 3000))
my_cols = [random.choice(string.ascii_uppercase) for x in range(matrix.shape[1])]
mydf = pd.DataFrame(matrix, columns=my_cols)
mydf['something'] = 'hello_world'

将HDF5的压缩率设置为最高:

store = pd.HDFStore('myfile.h5',complevel=9, complib='bzip2')
store['mydf'] = mydf
store.close()

同时保存为CSV文件:

mydf.to_csv('myfile.csv', sep=':')

结果为:

  • myfile.csv 大小为5.6 MB
  • myfile.h5 大小为11 MB

数据集越大,差异越大。

我已尝试使用其他压缩方法和级别。这是一个错误吗?(我正在使用Pandas 0.11和HDF5以及Python的最新稳定版本)。


8
据我所知,HDF5 的设计旨在优化查找时间,而不是文件大小。 - Joran Beasley
字符串列也使用每列固定的大小(即所有列的最大大小)。请在文档中阅读有关min_itemsize的内容。 - Jeff
请参考我上面的评论:http://pandas.pydata.org/pandas-docs/dev/io.html#string-columns。此外,你的测试只是展示了HDF5中一点点的开销。这是非常结构化的数据;尝试使用100万行浮点数进行相同的测试,你会感到惊讶的。 - Jeff
1
非常感谢Jeff。我仍然对此存在疑惑。我创建的矩阵有100 x 3000 = 300,000个float64值,只有100个字符串,且它们都保存着相同的值,我想这应该能从压缩中获益。但是,即使我使用了最高级别的压缩方案,它仍然比CSV文件占用更多的空间。这是正常的吗? - Amelio Vazquez-Reina
@user815423426 我的经验和你一样 - HDF5 占用的空间比 CSV 多得多。 - Jeff Tratner
1个回答

52

这是我从问题页面复制的回答:https://github.com/pydata/pandas/issues/3651

你提供的样本实在太小了。对于非常小的尺寸(即使300k条目),HDF5都有相当多的开销。以下内容是在任意一侧均不压缩的情况下。浮点数在二进制中表示更高效(而不是文本表示)。

此外,HDF5是基于行的。如果表不太宽但是相当长,则可以获得更高的效率。(因此,在这种情况下,将示例转置存储并不是很有效)我经常拥有超过10M行的表格,并且查询时间可以在毫秒内完成。即使下面的示例很小,拥有10GB以上的文件也很常见(更不用说天文学家们的10GB +只需几秒钟!)

-rw-rw-r--  1 jreback users 203200986 May 19 20:58 test.csv
-rw-rw-r--  1 jreback users  88007312 May 19 20:59 test.h5

In [1]: df = DataFrame(randn(1000000,10))

In [9]: df
Out[9]: 
<class 'pandas.core.frame.DataFrame'>
Int64Index: 1000000 entries, 0 to 999999
Data columns (total 10 columns):
0    1000000  non-null values
1    1000000  non-null values
2    1000000  non-null values
3    1000000  non-null values
4    1000000  non-null values
5    1000000  non-null values
6    1000000  non-null values
7    1000000  non-null values
8    1000000  non-null values
9    1000000  non-null values
dtypes: float64(10)

In [5]: %timeit df.to_csv('test.csv',mode='w')
1 loops, best of 3: 12.7 s per loop

In [6]: %timeit df.to_hdf('test.h5','df',mode='w')
1 loops, best of 3: 825 ms per loop

In [7]: %timeit pd.read_csv('test.csv',index_col=0)
1 loops, best of 3: 2.35 s per loop

In [8]: %timeit pd.read_hdf('test.h5','df')
10 loops, best of 3: 38 ms per loop

我真的不会担心大小(我猜你也不是,只是有点好奇,这很好)。 HDF5的重点在于磁盘很便宜,CPU很便宜,但你不能将所有东西都放在内存中,所以我们通过使用分块来进行优化。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接