为啥用 Pandas 编写时 CSV 文件比 HDF5 文件小?

Posted

技术标签:

【中文标题】为啥用 Pandas 编写时 CSV 文件比 HDF5 文件小?【英文标题】:Why are CSV files smaller than HDF5 files when writing with Pandas?为什么用 Pandas 编写时 CSV 文件比 HDF5 文件小? 【发布时间】:2015-05-10 04:52:41 【问题描述】:
import numpy as np
import pandas as pd

df = pd.DataFrame(data=np.zeros((1000000,1)))
df.to_csv('test.csv')
df.to_hdf('test.h5', 'df')

ls -sh test*
11M test.csv  16M test.h5

如果我使用更大的数据集,那么效果会更大。使用像下面这样的HDFStore 不会改变任何事情。

store = pd.HDFStore('test.h5', table=True)
store['df'] = np.zeros((1000000,1))
store.close()

编辑: 没关系。例子很糟糕!使用一些重要的数字而不是零会改变故事。

from numpy.random import rand
import pandas as pd

df = pd.DataFrame(data=rand(10000000,1))
df.to_csv('test.csv')
df.to_hdf('test.h5', 'df')

ls -sh test*
260M test.csv  153M test.h5

将数字表示为浮点数应该比将它们表示为每个数字一个字符的字符串需要更少的字节。这通常是正确的,除了在我的第一个示例中,所有数字都是“0.0”。因此,表示数字所需的字符并不多,因此字符串表示小于浮点表示。

【问题讨论】:

【参考方案1】:

简单地说:

csv 文件是“哑”的:它一次只有一个字符,所以如果您打印(例如,四字节)浮点 1.0 到十位数字,您确实使用了那么多字节 - 但好消息是不是csv压缩得好,所以考虑.csv.gz

hdf5 是一种元格式没有免费午餐定理仍然成立:条目和值需要存储在某处。这可能会使 hdf5 更大。

但您忽略了一个更大的问题:csv 只是文本。其精度有限——而 hdf5 是几种以更高精度存储数据的 binary (序列化)格式之一。在这方面也确实是苹果对橘子。

【讨论】:

CSV 在什么意义上具有有限的精度?您始终可以写出包含与二进制文件完全相同的信息的 CSV。通常它不那么紧凑(至少在压缩之前)并且几乎总是更慢,但你不应该丢失任何信息,除非你在写出值之前故意舍入或截断。 理论上是正确的,实际上我从未见过 16 位小数的 csv 文件。 是的,我同意这一点。只是澄清一下 CSV(和一般的文本)在本质上并不比二进制更精确。【参考方案2】:

对于.csv,您的方法存储如下字符:

999999,0.0<CR>

每个值最多 11 个字符。在 100 万个值时,这接近 11MB。

HD5 似乎将每个值存储为 16 字节浮点数,不要介意它一遍又一遍地是相同的值。所以这是 16 字节 * 1,000,000,大约是 16 MB。

存储的不是 0.0,而是一些随机数据,.csv 文件很快就会增加到 25MB 甚至更多,而 HDF5 文件的大小保持不变。虽然 csv 文件失去了准确性,但 HDF5 保留了它。

【讨论】:

以上是关于为啥用 Pandas 编写时 CSV 文件比 HDF5 文件小?的主要内容,如果未能解决你的问题,请参考以下文章

python用pandas工具包来处理.csv文件,包括读写和切片

用pandas编写单个CSV标头

为啥 Pandas 在 read_csv 时会导致 ZeroDivisionError

为啥 dask 的“to_sql”比 pandas 花费更多时间?

如何使用 Python 和 Pandas 创建比 RAM 更大的 csv 文件

Python CSV to JSON:为啥 JSON 比 CSV 文件大得多,如何修复?