Python 将多节点PyTable转换为bcolz

Python 将多节点PyTable转换为bcolz,python,hdf5,pytables,bcolz,Python,Hdf5,Pytables,Bcolz,我想尝试一下bcolz,看看它是否与我需要做的事情兼容。我有一个由大约1100万行和大约120列组成的数据集。该数据当前以PyTables“table”格式存储在HDF5文件中。在HDF5文件中,数据被分成几个“组”(单独的节点),每个组包含不同的列 我想做的是将所有这些数据转换成磁盘上的bcolz ctable,而无需立即将其全部读入内存。通过这样做,我可以为第一个组做到这一点(basic是其中一个组的名称): 当我这样做时,内存使用率仍然很低,这表明它没有一次读取整个表。伟大的但是,如果我尝

我想尝试一下bcolz,看看它是否与我需要做的事情兼容。我有一个由大约1100万行和大约120列组成的数据集。该数据当前以PyTables“table”格式存储在HDF5文件中。在HDF5文件中,数据被分成几个“组”(单独的节点),每个组包含不同的列

我想做的是将所有这些数据转换成磁盘上的bcolz ctable,而无需立即将其全部读入内存。通过这样做,我可以为第一个组做到这一点(
basic
是其中一个组的名称):

当我这样做时,内存使用率仍然很低,这表明它没有一次读取整个表。伟大的但是,如果我尝试再次执行此操作,请在相同的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.ctable.fromhdf5('census.h5','/political/table',rootdir='census',mode='a')
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
bcolz.ctable.fromhdf5('census.h5','/political/table',rootdir='census',mode='a')
文件“C:\FakeProgs\Python27\lib\site packages\bcolz\ctable.py”,第714行,fromhdf5
ct=ctable(列、名称,**kwargs)
文件“C:\FakeProgs\Python27\lib\site packages\bcolz\ctable.py”,第205行,在_init中__
“不能在'a'ppend模式下传递'columns'参数。\n”
ValueError:无法在“a”结束模式下传递“columns”参数。
(如果您试图创建一个新的ctable,可能该目录已经存在。)

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

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

请参阅下面的代码以了解大致方向。其灵感来源于,但未经测试:

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文件在内存中创建一个表,然后将列复制到第一个表不同。我假设这就是你对
的意思,而不将所有新列读入内存

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)