向表格(HDF5)数据库追加大量数据时,数据库.numcols与新数据.numcols不相等怎么办?

3 投票
2 回答
2291 浏览
提问于 2025-04-17 01:37

我正在尝试把一个很大的数据集(超过30GB)添加到一个已经存在的pytables表格里。这个表格有N列,而我的数据集只有N-1列;其中一列是在我知道其他N-1列的数据后才能计算出来的。

我使用numpy.fromfile()来把数据集的一部分读入内存,然后再把它添加到数据库里。理想情况下,我希望先把数据放进数据库,然后计算出最后一列,最后再用Table.modifyColumn()来完成这个操作。

我考虑过先把numpy.zeros((len(new_data), N))添加到表格中,然后再用Table.modifyColumns()来填充新的数据,但我希望有人能告诉我一个更好的方法,这样我就不需要为每一块要添加的数据生成一个巨大的空数组了。

2 个回答

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)
2

如果所有的列都是同一种类型的数据,你可以使用 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。虽然这个方法会把数据复制到一个新的数组里,所以不会节省太多内存,但它可以让你一次性完成所有的写入操作。

撰写回答