0

我希望对 bcolz 进行一些实验,看看它是否与我需要做的兼容。我有一个由大约 1100 万行和大约 120 列组成的数据集。此数据当前以 PyTables“表”格式存储在 HDF5 文件中。数据在 HDF5 文件中分为几个“组”(单独的节点),每个组包含不同的列。

我想要做的是将所有这些数据转换为磁盘上的 bcolz ctable,而不是一次将其全部读入内存。通过这样做,我能够为第一组做到这一点(basic是其中一个组的名称):

bcolz.ctable.fromhdf5('census.h5', '/basic/table', rootdir='census')

当我这样做时,内存使用率仍然很低,表明它没有立即读取整个表。伟大的!但是,如果我尝试再次执行此操作,则附加到同一个 ctable:

>>> bcolz.ctable.fromhdf5('census.h5', '/political/table', rootdir='census', mode='a')
Traceback (most recent call last):
  File "<pyshell#34>", line 1, in <module>
    bcolz.ctable.fromhdf5('census.h5', '/political/table', rootdir='census', mode='a')
  File "C:\FakeProgs\Python27\lib\site-packages\bcolz\ctable.py", line 714, in fromhdf5
    ct = ctable(cols, names, **kwargs)
  File "C:\FakeProgs\Python27\lib\site-packages\bcolz\ctable.py", line 205, in __init__
    "You cannot pass a `columns` param in 'a'ppend mode.\n"
ValueError: You cannot pass a `columns` param in 'a'ppend mode.
(If you are trying to create a new ctable, perhaps the directory exists already.)

是的,当然它已经存在了。bcolz 的优点之一应该是很容易添加新列。如何利用这一优势将现有 HDF5 文件中的新列直接添加到现有的磁盘 ctable 中,而无需先将所有新列读入内存?

4

1 回答 1

2

一个想法可能是利用这样一个事实,即在向 a 添加列时ctable,如果该列是现有的carray,您可以请求移动磁盘文件(这是立即的)而不是复制它。所以可以先为 hdf5 表的每一列创建一个数组,然后将其添加到ctable.

有关一般方向,请参见下面的代码。它的灵感来自bcolz 如何从 hdf5 文件创建表,并且未经测试:

table = bcolz.ctable.fromhdf5('census.h5', '/basic/table', rootdir='census')

fp = tables.open_file('census.h5')
h5table = fp.get_node('/political/table')
for colname in h5table.colnames:
    h5column = h5table.colinstances[colname]
    #create the column
    coltype = h5table.coldtypes[colname]
    nparr = np.zeros(0, dtype=coltype)
    column = bcolz.carray(nparr, mode='w', rootdir='tmpcol')

    #Fill it in chunks
    chunklen = h5table._v_chunkshape[0]
    for i in xrange(0, len(h5table), chunklen):
        column.append(h5column[i:i+chunklen])
    column.flush()

    #Add column to table without copying
    table.addcol(column, name=colname, move=True)

我同意在 blocz 中有这个功能会很好,但我猜这个包还很年轻。也许你可以添加它!:) 另请注意,在将数据存储到 bcolz 表之前,数据将被读入内存。但它只会被读取一次,并且是分块读取的,这与您首先从 h5 文件创建内存表并将列复制到第一个表不同。我假设这就是你的意思without reading all the new columns into memory

于 2015-10-21T12:53:19.163 回答