如何将一小撮元组数组解压缩为ndarray?

时间:2019-04-25 15:07:03

标签: python numpy

我有一个二维numpy数组,其元素类型为np.void,本质上是元组。有没有一种有效的方法可以将这些元组中的值解压缩到第3维,而无需循环遍历数组的每个元素?

例如,二维数组如下所示:

a = np.array([[(1, 2,  3), (1, 2,  3), (1, 2, 3)],
       [(1, 2,  3), (1, 2, 3), (1, 2, 3)],
       [(1, 2, 3), (1, 2, 3), (1, 2, 3)]],
      dtype=[('B4', '<u2'), ('B3', '<u2'), ('B2', '<u2')])

在哪里

a.shape = (3,3)
a[0,0] = (1,2,3)

我想解压每个元素,以便得到的阵列为3D 看起来像这样:

b.shape = (3,3,3)
b[0,0,0] = 1
b[0,0,1] = 2
b[0,0,2] = 3

换句话说,

b[:,:,0] == 
array([[1, 1, 1],
       [1, 1, 1],
       [1, 1, 1]])
b[:,:,1] == 
array([[2, 2, 2],
       [2, 2, 2],
       [2, 2, 2]])
b[:,:,2] == 
array([[3, 3, 3],
       [3, 3, 3],
       [3, 3, 3]])

我知道除了循环遍历每个元素外,还有一种更有效的方法,但是我对np.void元素的处理并不十分熟悉。

谢谢

为澄清起见,a more efficient solution与类似的内容相比

new_array = np.zeros((a.shape + (3,)))
for i in range(a.shape[0]):
    for j in range(a.shape[-1]):
        new_array[i, j, 0] = a[i, j][0]
        new_array[i, j, 1] = a[i, j][1]
        new_array[i, j, 2] = a[i, j][2]

2 个答案:

答案 0 :(得分:0)

您可以将其作为标准的numpy数组进行查看,以允许进行索引。

b = a.view('(3,)<u2')

array([[[1, 2, 3],
        [1, 2, 3],
        [1, 2, 3]],

       [[1, 2, 3],
        [1, 2, 3],
        [1, 2, 3]],

       [[1, 2, 3],
        [1, 2, 3],
        [1, 2, 3]]], dtype=uint16)

>>> b.shape
(3, 3, 3)
>>> b[:, :, 0]
array([[1, 1, 1],
       [1, 1, 1],
       [1, 1, 1]], dtype=uint16)

答案 1 :(得分:0)

In [601]: a = np.array([[(1, 2,  3), (1, 2,  3), (1, 2, 3)], 
     ...:        [(1, 2,  3), (1, 2, 3), (1, 2, 3)], 
     ...:        [(1, 2, 3), (1, 2, 3), (1, 2, 3)]], 
     ...:       dtype=[('B4', '<u2'), ('B3', '<u2'), ('B2', '<u2')])                 
In [602]: a.dtype                                                                    
Out[602]: dtype([('B4', '<u2'), ('B3', '<u2'), ('B2', '<u2')])
In [603]: a.shape                                                                    
Out[603]: (3, 3)

这是具有复合dtype的结构化数组。元组显示2d数组的各个元素。

最近的numpy版本添加了一个功能,可以方便地将结构化数组转换为非结构化数组:

In [606]: b=rf.structured_to_unstructured(a)                                         
In [607]: b                                                                          
Out[607]: 
array([[[1, 2, 3],
        [1, 2, 3],
        [1, 2, 3]],

       [[1, 2, 3],
        [1, 2, 3],
        [1, 2, 3]],

       [[1, 2, 3],
        [1, 2, 3],
        [1, 2, 3]]], dtype=uint16)
In [608]: b[:,:,1]                                                                   
Out[608]: 
array([[2, 2, 2],
       [2, 2, 2],
       [2, 2, 2]], dtype=uint16)

a有3个字段。可以按名称访问各个字段:

In [610]: a['B4']                                                                    
Out[610]: 
array([[1, 1, 1],
       [1, 1, 1],
       [1, 1, 1]], dtype=uint16)

这意味着您可以通过串联3个单独的字段来构造3d数组:

np.stack([a['B4'],a['B3'],a['B2']]) 

这就像您的最后一个解决方案,但没有进行i,j迭代。


在这种情况下,其他答案中的view方法是可行的,因为所有字段都具有相同的dtype<u2。这意味着可以将相同的基础数据视为单独的<u2元素,或其中的3个元素。

rf.structured_to_unstructured适用于view不适用的更一般情况,例如dtypes的混合(例如浮点数和整数)。