在删除axis0的第I个索引的子元素的同时创建平铺的多维数组?

时间:2017-01-21 13:35:59

标签: python numpy tiling

我试图平铺一个数组,其中每个索引都是多层次的。 然后我从每个索引中删除第i个子元素。

例如,从这个数组开始:

>>> a = np.array([[    1.     ,     7.     ,     0.     ],
                  [    2.     ,     7.     ,     0.     ],
                  [    3.     ,     7.     ,     0.     ]])
>>> a = np.tile(a, (a.shape[0],1,1))

>>> print a
array([[[    1.     ,     7.     ,     0.     ],
        [    2.     ,     7.     ,     0.     ],
        [    3.     ,     7.     ,     0.     ]],

       [[    1.     ,     7.     ,     0.     ],
        [    2.     ,     7.     ,     0.     ],
        [    3.     ,     7.     ,     0.     ]],

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

期望的输出:

b = np.array([[[    2.     ,     7.     ,     0.     ],
               [    3.     ,     7.     ,     0.     ]],

              [[    1.     ,     7.     ,     0.     ],
               [    3.     ,     7.     ,     0.     ]],

              [[    1.     ,     7.     ,     0.     ],
               [    2.     ,     7.     ,     0.     ]]])

我想知道是否有更有效的方法来生成此输出而不必先创建一个大型数组然后从中删除它?

[UPDATE]

这种排列背后的意图是尝试向量化而不是使用python for-loops。 Divakar提供的答案对完成这项任务有很大帮助。我还想链接到this post,它显示了这种排列的反转,并且在我完成时重新排列所有值的有用之处。

此外,我试图在Tensorflow的张量上使用相同的置换技术(请参阅this post

1 个答案:

答案 0 :(得分:4)

方法#1:这是一种创建索引的2D数组的方法,以便在每个i-th位置跳过这些索引,然后使用它进行索引进入输入数组的第一个轴 -

def approach1(a):
    n = a.shape[0]
    c = np.nonzero(~np.eye(n,dtype=bool))[1].reshape(n,n-1) # dim0 indices
    return a[c]

示例运行 -

In [272]: a
Out[272]: 
array([[56, 95],
       [31, 73],
       [76, 61]])

In [273]: approach1(a)
Out[273]: 
array([[[31, 73],
        [76, 61]],

       [[56, 95],
        [76, 61]],

       [[56, 95],
        [31, 73]]])

方法#2:以下是使用np.broadcast_to创建扩展视图到输入数组的另一种方式,然后将其屏蔽以获得所需的输出 -

def approach2(a):
    n = a.shape[0]
    mask = ~np.eye(n,dtype=bool)
    return np.broadcast_to(a, (n, n, a.shape[-1]))[mask].reshape(n,n-1,-1)

运行时测试

In [258]: a = np.random.randint(11,99,(200,3))

In [259]: np.allclose(approach1(a), approach2(a))
Out[259]: True

In [260]: %timeit approach1(a)
1000 loops, best of 3: 1.43 ms per loop

In [261]: %timeit approach2(a)
1000 loops, best of 3: 1.56 ms per loop