广播高级索引numpy

时间:2015-06-25 02:11:48

标签: python numpy

我有一个值数组,例如

x = array([[[-0.78867513, -0.21132487,  0.        ,  0.78867513,  0.21132487,    0.        ,  0.        ,  0.        ,  0.        ],
            [ 0.        , -0.78867513, -0.21132487,  0.        ,  0.78867513,    0.21132487,  0.        ,  0.        ,  0.        ],
            [ 0.        ,  0.        ,  0.        , -0.78867513, -0.21132487,    0.        ,  0.78867513,  0.21132487,  0.        ],
            [ 0.        ,  0.        ,  0.        ,  0.        , -0.78867513,   -0.21132487,  0.        ,  0.78867513,  0.21132487]],
           [[-0.78867513, -0.21132487,  0.        ,  0.78867513,  0.21132487,    0.        ,  0.        ,  0.        ,  0.        ],
            [ 0.        , -0.78867513, -0.21132487,  0.        ,  0.78867513,    0.21132487,  0.        ,  0.        ,  0.        ],
            [ 0.        ,  0.        ,  0.        , -0.78867513, -0.21132487,    0.        ,  0.78867513,  0.21132487,  0.        ],
            [ 0.        ,  0.        ,  0.        ,  0.        , -0.78867513,   -0.21132487,  0.        ,  0.78867513,  0.21132487]]])

我想使用高级索引来提取非零值。我知道非零值的索引,所以

idx = array([[4, 3, 1, 0],
             [5, 4, 2, 1],
             [7, 6, 4, 3],
             [8, 7, 5, 4]])

期望的结果将类似于

x[idx] = array([[[-0.78867513, -0.21132487,  0.78867513,  0.21132487],
                 [-0.78867513, -0.21132487,  0.78867513,  0.21132487],
                 [-0.78867513, -0.21132487,  0.78867513,  0.21132487],
                 [-0.78867513, -0.21132487,  0.78867513,  0.21132487]],
                [[-0.78867513, -0.21132487,  0.78867513,  0.21132487],
                 [-0.78867513, -0.21132487,  0.78867513,  0.21132487],
                 [-0.78867513, -0.21132487,  0.78867513,  0.21132487],
                 [-0.78867513, -0.21132487,  0.78867513,  0.21132487]]])

第一维的实际x数组要大得多,但非零结构始终由idx表示,所以我需要它沿第一维广播。这可能吗?

编辑:要明确第一维的x包含4 x 9数组的嵌套列表。 idx然后有非行条目换行。请注意4 x 9x个嵌套数组的第一行中4 3 1 0条目非零。

3 个答案:

答案 0 :(得分:1)

试试这个:

x[:,np.arange(idx.shape[0])[:,None],idx]

使用此技术np.arange(idx.shape[0])[:,None]中的每个元素(其形状(idx.shape [0],1)因此是列向量)将与idx中的每一行一起广播。然后,这将用于沿x的第一个轴的所有条目。

答案 1 :(得分:0)

好的,这有点奇怪,但是这里......

idxes = np.ones((x.shape[0], x.shape[1], 1), dtype=bool) * idx
print x[np.array(x, dtype=bool)].reshape(idxes.shape)

当然,你必须记得写np.array而不是array

干杯!

你可以通过以下方式解除计算idx的负担:

y = x[np.array(x, dtype=bool)]
print y.reshape(x.shape[0], x.shape[1], y.size/x.shape[0]/x.shape[1])

通过这个或上面的线条,浮子的铸造为bool,提供了一个消除零点的掩模。

答案 2 :(得分:0)

我为你的问题试了一个班轮,似乎没有function(){return(mycount.toString(););} 就完成了工作。您可能需要根据问题的大小更改idx中的参数。

.reshape()

它使数组变平,移除零,然后将其更改回所需的形状。

这是另一个可能更高效的版本,因为它不使用np.array(filter(lambda x: x!=0, x.ravel())).reshape(-1, 4, 4) 函数并使用布尔索引代替numpy数组

filter

修改

在玩numpy时我发现了另一种方法。

y = x.ravel()
z = y[y!=0].reshape(-1, 4, 4)

这是所有三种方法的表现:

  • 方法1:x[x!=0].reshape(-1, 4, 4)
  • 方法2:10000 loops, best of 3: 21.2 µs per loop
  • 方法3:100000 loops, best of 3: 2.42 µs per loop