PyTables:索引大型数组的多个维度

时间:2012-06-16 23:52:42

标签: python numpy hdf5 pytables

我正在分析一些成像数据,这些数据由尺寸为[frame, x, y]的大型三维像素强度阵列组成。由于它们通常太大而无法保存在内存中,因此它们作为PyTables数组驻留在硬盘上。

我希望能够读出所有帧中任意像素子集的强度。这样做的自然方式似乎是列表索引:

import numpy as np
import tables

tmph5 = tables.open_file('temp.hdf5', 'w')
bigarray = tmph5.create_array('/', 'bigarray', np.random.randn(1000, 200, 100))

roipixels = [[0, 1, 2, 4, 6], [34, 35, 36, 40, 41]]
roidata = bigarray[:, roipixels[0], roipixels[1]]
# IndexError: Only one selection list is allowed

不幸的是,似乎PyTables目前只支持一组列表索引。另一个问题是列表索引不能包含重复项 - 我无法同时读取像素[1, 2][1, 3],因为我的像素x坐标列表将包含[1, 1]。我知道我可以迭代数组中的行:

roidata = np.asarray([row[roipixels[0], roipixels[1]] for row in bigarray])

但是对于我正在处理的大量帧,这些迭代读取变得非常慢。

有更好的方法吗?我对PyTables比较陌生,所以如果您有关于在大型数组中组织数据集的任何提示,我很乐意听到它们。

1 个答案:

答案 0 :(得分:2)

无论价值多少,我经常用以hdf格式存储的三维地震数据做同样的事情。

由于嵌套循环,迭代读取很慢。如果你只做一个循环(而不是循环遍历每一行),它的速度非常快(至少在使用h5py时。我通常只使用pytables存储类似数据的数据),并且完全符合你的要求。

在大多数情况下,您需要遍历您的指标列表,而不是遍历每一行。

基本上,你想:

roidata = np.vstack([bigarray[:,i,j] for i,j in zip(*roipixels)])

而不是:

roidata = np.asarray([row[roipixels[0],roipixels[1]] for row in bigarray])

如果这是您最常见的用例,调整存储阵列的块大小将有助于显着提高。在你的情况下,你需要长而窄的块,沿第一轴的长度最长。

(警告:我没有使用pytables对此进行测试,但它与h5py完美匹配。)