通过沿轴应用tuple()沿轴挤压ndarray

时间:2019-06-10 06:12:16

标签: python python-3.x numpy

给出一个ndarray,我想沿一个轴挤压它,这样沿该维度的元素将形成元组,即。 e。它将产生ndarray个元组,其维数比父ndarray小一维。

假设我下面有一个三维数组,它基本上是由numpy.indices从一个二维数组中生成的。

    idx = array([[[0, 0, 0, 0],
                  [1, 1, 1, 1],
                  [2, 2, 2, 2]],

                 [[0, 1, 2, 3],
                  [0, 1, 2, 3],
                  [0, 1, 2, 3]]])

我尝试将numpy.apply_along_axistuple()一起使用。

numpy.apply_along_axis(tuple, 0, idx)

它没有用。因此,在tuple()周围创建了一个虚拟包装器,并传递了该函数以检查tuple()是否按预期工作。

def dtuple(x):
    print(tuple(x))
    return tuple(x)

输出为:

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

       [[0, 1, 2, 3],
        [0, 1, 2, 3],
        [0, 1, 2, 3]]])

很显然,tuple()正常工作,但是奇怪的是,它没有返回ndarray个对象的tuple,而是返回了相同的ndarray。我还尝试传递idx.astype(object)而不是仅传递idx,但这也不起作用。请注意,我试图避免在这里for循环。预期输出如下:

array([[(0, 0), (0, 1), (0, 2), (0, 3)],
       [(1, 0), (1, 1), (1, 2), (1, 3)],
       [(2, 0), (2, 1), (2, 2), (2, 3)]], dtype=object)

1 个答案:

答案 0 :(得分:1)

让我们尝试一些替代方法:

In [563]: x=np.arange(12).reshape(3,4)                                                                 
In [564]: np.apply_along_axis(lambda i:[12],1,x)                                                       
Out[564]: 
array([[12],
       [12],
       [12]])
In [565]: np.apply_along_axis(lambda i:(1,2,3),1,x)                                                    
Out[565]: 
array([[1, 2, 3],
       [1, 2, 3],
       [1, 2, 3]])
In [566]: np.apply_along_axis(lambda i:i,1,x)                                                          
Out[566]: 
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])
In [567]: np.apply_along_axis(lambda i:i*2,1,x)                                                        
Out[567]: 
array([[ 0,  2,  4,  6],
       [ 8, 10, 12, 14],
       [16, 18, 20, 22]])

看一下文档:

out : ndarray  (Ni..., Nj..., Nk...)
    The output array. The shape of `out` is identical to the shape of
    `arr`, except along the `axis` dimension. This axis is removed, and
    replaced with new dimensions equal to the shape of the return value
    of `func1d`. So if `func1d` returns a scalar `out` will have one
    fewer dimensions than `arr`.

无论函数是否返回数字,列表,元组或数组,它仍将其作为维。 dtype仍为数字。

您为什么要避免循环? apply_along_axis不会避免循环,只会将其隐藏在函数中。

这是一个不错的循环:

In [578]: arr = np.empty(x.shape[0],object)                                                            
In [579]: for i,v in enumerate(x): 
     ...:     arr[i] = tuple(v.tolist()) 
     ...:                                                                                              
In [580]: arr                                                                                          
Out[580]: array([(0, 1, 2, 3), (4, 5, 6, 7), (8, 9, 10, 11)], dtype=object)

====

使用您的idx,这是通过结构化数组的一种方法。比我想要的要复杂得多,但这是我睡觉的时间。

In [596]: arr = np.zeros((3,4),'i,i')                                                                  
In [597]: arr['f0']=idx[0]                                                                             
In [598]: arr['f1']=idx[1]                                                                             
In [599]: arr                                                                                          
Out[599]: 
array([[(0, 0), (0, 1), (0, 2), (0, 3)],
       [(1, 0), (1, 1), (1, 2), (1, 3)],
       [(2, 0), (2, 1), (2, 2), (2, 3)]],
      dtype=[('f0', '<i4'), ('f1', '<i4')])
In [600]: arr.tolist()                                                                                 
Out[600]: 
[[(0, 0), (0, 1), (0, 2), (0, 3)],
 [(1, 0), (1, 1), (1, 2), (1, 3)],
 [(2, 0), (2, 1), (2, 2), (2, 3)]]
In [601]: arr1=np.empty((3,4),object)                                                                  
In [602]: arr1[...] = _600                                                                             
In [603]: arr1                                                                                         
Out[603]: 
array([[(0, 0), (0, 1), (0, 2), (0, 3)],
       [(1, 0), (1, 1), (1, 2), (1, 3)],
       [(2, 0), (2, 1), (2, 2), (2, 3)]], dtype=object)