Python 如何减少HDFStore的大小开销?

Python 如何减少HDFStore的大小开销?,python,pandas,hdfstore,Python,Pandas,Hdfstore,我正在试验不同的熊猫友好型蜱虫数据存储方案。到目前为止,最快的(在读写方面)是使用带blosc压缩和“固定”格式的HDFStore 我用股票代码索引,因为这是我常用的访问模式。但是,此方案为每个符号增加了大约1MB的空间。也就是说,如果microcap股票的数据帧当天只包含1000个刻度,则该文件的大小将增加1兆字节。因此,对于大量的小型股票来说,.h5文件很快就会变得难以处理 有没有一种方法可以保持blosc/fixed格式的性能优势,同时减小大小?我尝试过“table”格式,每个符号大约需要

我正在试验不同的熊猫友好型蜱虫数据存储方案。到目前为止,最快的(在读写方面)是使用带blosc压缩和“固定”格式的HDFStore

我用股票代码索引,因为这是我常用的访问模式。但是,此方案为每个符号增加了大约1MB的空间。也就是说,如果microcap股票的数据帧当天只包含1000个刻度,则该文件的大小将增加1兆字节。因此,对于大量的小型股票来说,
.h5
文件很快就会变得难以处理

有没有一种方法可以保持blosc/fixed格式的性能优势,同时减小大小?我尝试过“table”格式,每个符号大约需要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中每个节点的大小惩罚。

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

以下是一些建议:

  • 您可以使用选项
    chunkshape='auto'
    重新打包文件。这将使用chunkshape进行打包,chunkshape是通过查看所有数据计算出来的,可以以更有效的块大小重新打包数据,从而产生更小的文件大小。原因是需要通知PyTables最终数组/表大小的预期行数

  • 通过传递
    expectedrows=
    (并且只执行一次附加),可以在
    格式中获得最佳的chunksize。然而,
    ptrepacking
    在这里仍然有好处

  • 您也可以尝试以表格格式写入,而不是设置所有
    data\u columns=True
    ,只需传递
    format='Table'
    ;它将写入表格式(但除了索引外,您将无法查询);但它存储为单个块,因此应该几乎与固定块一样快(但更节省空间)

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

通过一些示例和解释,这进一步增强了这一点。对于我的Pandas(1.2.3)和PyTables(3.6.1)版本,我在访问HDF存储时看到以下行为:

将熊猫作为pd导入
df=pd.DataFrame([[1,“a”],[2,“b”],[3,“c”])
#创建一个固定格式的存储:会造成相当大的内存开销!
#文件大小store1.h5:1.1MB
store=pd.HDFStore(“store1.h5”)
store.put(key=“some/key”,value=df,format=“fixed”)
store.close()
#更好:创建一个表格式的存储。
#文件大小store1.h5:86kB!
store=pd.HDFStore(“store2.h5”)
store.put(key=“some/key”,value=df,format=“table”)
store.close()
注意:不要使用商店,直接使用:

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)大大降低了内存开销。在更现实的情况下,数据量越大,这种开销就越小。固定格式存储允许快速读/写操作,而表格式更灵活(有关详细信息,请参阅)。 例如,
格式可以比固定格式更好地处理混合数据类型(每列)。例如,请参见上面示例中使用
df.T.to_hdf(…)
时会发生什么。固定格式将发布以下PerformanceWarning(请参见on SO或pandas问题),而表格格式工作正常

PerformanceWarning:您的性能可能会受到影响,因为PyTables将受到影响
无法直接映射到c类型的对象类型
ptrepack
是随附的命令行实用程序(包名为
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存储的存储开销是否合理取决于您的应用程序。

AFAIK对于PyTables中的块大小,它们是一个特定的最小值;您可以查看
ptrepack
文件的各种选项。最低1MB可能是合理的IMHO。您也可以尝试以
表格
格式写入,而不是设置所有
数据列=True
,只需传递
表格
;它将写入表格式(但除了索引外,您将无法查询);但它存储为单个块,因此应该几乎与固定块一样快(但更节省空间)。@Jeff有什么特别的选项我应该转到
ptrepack
?如果我不提供任何选项,则生成的文件大小相同。您可以尝试
chunkshape
;我不知道这是否会改变大小。@Jeff
chunkshape=auto
缩小了文件!我要用这个做个实验,看看结果如何。真的吗?太好了。仅供参考,他们在PyTables 3.1(刚刚发布)中也是一个新的blosc过滤器,请参见此处:;不确定更新后的blosc会做什么(我认为pandas会直接通过参数,如果它不起作用,请提交错误报告-目前pandas没有
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