如何减少HDFStore的大小开销?

时间:2014-02-07 18:33:21

标签: python pandas hdfstore

我正在试验不同的大熊猫友好存储方案,用于刻度数据。到目前为止,最快的(在读写方面)一直使用具有blosc压缩和“固定”格式的HDFStore。

store = pd.HDFStore(path, complevel=9, complib='blosc')
store.put(symbol, df)
store.close()

我正在使用股票代码进行索引,因为这是我常用的访问模式。但是,此方案为每个符号添加大约1 MB的空间 。也就是说,如果微型库存的数据框当天只包含一千个刻度,则文件的大小将增加一兆字节。因此,对于大量小型股票而言,.h5文件很快变得难以处理。

有没有办法保持blosc /固定格式的性能优势,但却缩小了尺寸?我尝试过“表格”格式,每个符号需要大约285 KB。

store.append(symbol, df, data_columns=True)

但是,这种格式的读写速度要慢得多。

如果有帮助,这就是我的数据框:

exchtime     datetime64[ns]
localtime    datetime64[ns]
symbol               object
country               int64
exch                 object
currency              int64
indicator             int64
bid                 float64
bidsize               int64
bidexch              object
ask                 float64
asksize               int64
askexch              object

blosc压缩本身运行良好,因为生成的.h5文件每行只需要30--35个字节。所以现在我主要担心的是降低HDFStore中每个节点的大小惩罚。

2 个答案:

答案 0 :(得分:3)

AFAIK在PyTables中块大小有一定的最小值。

以下是一些建议:

  • 您可以使用ptrepack选项chunkshape='auto'该文件。这将使用通过查看所有数据计算的块组合来打包它,并且可以在更有效的块大小中重新打包数据,从而导致更小的文件大小。原因是需要告知PyTables最终数组/表大小的预期行数。

  • 您可以通过传递Table(并且仅执行一次附加)以expectedrows=格式实现最佳chunksize。但是,ptrepacking仍然会带来好处。

  • 您也可以尝试以表格形式书写,而不是设置所有data_columns=True,只需传递format='table';它会写表格式(但你不能通过索引查询);但它存储为一个单独的块,所以应该几乎和固定一样快(但更节省空间)

  • 在PyTables 3.1(刚刚发布)中,有一个新的blosc过滤器。这可能会减少文件大小。 请参阅here

答案 1 :(得分:0)

这通过一些示例和解释增强了 previous answer。对于我的 Pandas (1.2.3) 和 PyTables (3.6.1) 版本,当 writing 到 HDF 存储时,我看到以下行为:

import pandas as pd
df = pd.DataFrame([[1, "a"], [2, "b"], [3, "c"]])

# Create a store with fixed format: creates considerable memory overhead!
# File size store1.h5: 1.1MB
store = pd.HDFStore("store1.h5")
store.put(key="some/key", value=df, format="fixed")
store.close()

# Better: create a store with table format.
# File size store1.h5: 86kB!
store = pd.HDFStore("store2.h5")
store.put(key="some/key", value=df, format="table")
store.close()

注意:不要使用商店,直接使用DataFrame.to_hdf()

df = pd.DataFrame([[1, "a"], [2, "b"], [3, "c"]])
df.to_hdf("store1.h5", key="some/key", format="fixed")
df.to_hdf("store2.h5", key="some/key", format="table")

在本例中,第二种方法(store2.h5)大大减少了内存开销。在更现实的情况下,随着数据量的增加,这种开销将变得不那么重要。固定格式存储允许快速读/写操作,而表格式更灵活(请参阅 docs 了解详细信息)。 例如,table 格式可以比固定格式更好地处理混合数据类型(每列)。例如,看看如果您在上述示例中使用 df.T.to_hdf(...) 会发生什么。固定格式将发出以下 PerformanceWarning(请参阅 SO 上的 this postthis pandas 问题),而表格格式工作正常。

PerformanceWarning: your performance may suffer as PyTables will pickle 
object types that it cannot map directly to c-types

ptrepackPyTables 附带的命令行实用程序(包名为 tables)。要查看 PyTables 的当前版本:python -m pip show tables.

使用 ptrepack,我可以通过应用一些压缩来进一步减小我的虚拟示例的文件大小。 (使用选项 --chunkshape=auto 没有明显效果。)

# store1.repack.h5: 1.1MB -> 22kB
ptrepack --complevel=9 --complib=blosc "store1.h5" "store1.repack.h5"
# store2.repack.h5: 86kB -> 9kB
ptrepack --complevel=9 --complib=blosc "store2.h5" "store2.repack.h5"

总而言之,以表格格式保存数据帧并通过压缩重新打包结果存储可以减少存储的内存占用。将 HDF 存储的存储开销降至最低是否合理取决于您的应用。

相关问题