向表格(HDF5)数据库追加大量数据时,数据库.numcols与新数据.numcols不相等怎么办?
我正在尝试把一个很大的数据集(超过30GB)添加到一个已经存在的pytables表格里。这个表格有N列,而我的数据集只有N-1列;其中一列是在我知道其他N-1列的数据后才能计算出来的。
我使用numpy.fromfile()
来把数据集的一部分读入内存,然后再把它添加到数据库里。理想情况下,我希望先把数据放进数据库,然后计算出最后一列,最后再用Table.modifyColumn()
来完成这个操作。
我考虑过先把numpy.zeros((len(new_data), N))
添加到表格中,然后再用Table.modifyColumns()
来填充新的数据,但我希望有人能告诉我一个更好的方法,这样我就不需要为每一块要添加的数据生成一个巨大的空数组了。
2 个回答
你可以把结果放到另一个表里。除非有特别的理由需要把计算出来的列放在其他列旁边,这样做可能是最简单的。其实,把原始数据和计算结果分开也是有好处的。
如果你一定要扩大表的大小,可以考虑使用 h5py。这个工具可以更直接地和h5文件进行交互。不过要注意,根据h5文件中数据集的创建方式,可能不能简单地在数据后面添加一列。有关一般数据格式的讨论,可以查看 http://www.hdfgroup.org/HDF5/doc/UG/03_DataModel.html 中的1.2.4节“数据空间”。如果底层数据集支持的话,h5py也支持 调整大小。
你也可以使用一个单独的缓冲区来存储输入数据,像这样:
z = zeros((nrows, N))
while more_data_in_file:
# Read a data block
z[:,:N-1] = fromfile('your_params')
# Set the final column
z[:,N-1:N] = f(z[:,:N-1])
# Append the data
tables_handle.append(z)
如果所有的列都是同一种类型的数据,你可以使用 numpy.lib.stride_tricks.as_strided
这个工具,把你从文件里读取的数组形状从 (L, N-1) 变成 (L, N)。举个例子,
In [5]: a = numpy.arange(12).reshape(4,3)
In [6]: a
Out[6]:
array([[ 0, 1, 2],
[ 3, 4, 5],
[ 6, 7, 8],
[ 9, 10, 11]])
In [7]: a.strides
Out[7]: (24, 8)
In [8]: b = numpy.lib.stride_tricks.as_strided(a, shape=(4, 4), strides=(24, 8))
In [9]: b
Out[9]:
array([[ 0, 1, 2, 3],
[ 3, 4, 5, 6],
[ 6, 7, 8, 9],
[ 9, 10, 11, 112]])
现在你可以用这个数组 b
来填充表格。每一行的最后一列和下一行的第一列是一样的,但在你计算出值的时候会覆盖掉这些重复的部分。
不过,如果 a
是记录数组(也就是有复杂的数据类型),这种方法就不适用了。对于这种情况,你可以试试 numpy.lib.recfunctions.append_fields
。虽然这个方法会把数据复制到一个新的数组里,所以不会节省太多内存,但它可以让你一次性完成所有的写入操作。