3

我正在尝试使用不同的熊猫友好型存储方案来存储刻度数据。到目前为止,最快的(就读写而言)是使用具有 blosc 压缩和“固定”格式的 HDFStore。

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

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

有没有办法保持 blosc/fixed 格式的性能优势但减小尺寸?我尝试过“表格”格式,每个符号需要大约 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 中每个节点的大小损失。

4

2 回答 2

4

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

以下是一些建议:

  • 您可以ptrepack使用选项chunkshape='auto'. 这将使用通过查看所有数据计算得出的块形状对其进行打包,并且可以将数据重新打包为更有效的块大小,从而导致文件大小更小。原因是 PyTables 需要被告知最终数组/表大小的预期行数。

  • 您可以通过传递(并且仅执行单个附加)以Table格式实现最佳块大小。expectedrows=但是,ptrepacking在这里仍然会有好处。

  • 也可以尝试用 Table 格式写,不用设置 all data_columns=True,直接通过format='table'; 它将写入表格格式(但您将无法通过索引查询);但它存储为单个块,因此应该几乎与固定一样快(但空间效率更高)

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

于 2014-02-07T22:15:48.017 回答
0

这通过一些示例和解释来补充先前的答案。对于我的 Pandas (1.2.3) 和 PyTables (3.6.1) 版本,我在写入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) 显着减少了内存开销。在更现实的情况下,随着数据量的增加,这种开销将变得不那么重要。固定格式存储允许快速读/写操作,而表格式更灵活(有关详细信息,请参阅文档)。例如,该格式可以比固定格式更好地table处理混合数据类型(每列)。例如,看看如果你df.T.to_hdf(...)在上面的例子中使用会发生什么。固定格式将发出以下 PerformanceWarning(请参阅SO 上的这篇文章或这个pandas 问题),而表格格式可以正常工作。

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

ptrepack是PyTables附带的一个命令行实用程序(包名为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 存储的存储开销是否合理取决于您的应用程序。

于 2021-04-12T22:55:21.977 回答