将多节点PyTable转换为bcolz

时间:2015-10-16 21:33:22

标签: python hdf5 pytables bcolz

我正在尝试用bcolz进行一些实验,看看它是否与我需要做的兼容。我有一个由大约1,100万行和大约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,而无需先将所有新列读入内存?

1 个答案:

答案 0 :(得分:2)

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

请参阅下面的代码以获取总体方向。它的灵感来自how bcolz create a table from a hdf5 file,未经过测试:

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