Numpy:依赖于列的切片

时间:2015-01-26 18:58:22

标签: python numpy

我找不到任何关于我想做什么的问题,所以我现在就问。基本上,我想在矩阵中切片,其中行索引取决于列索引。

例如:

>>> import numpy as np
>>> x = np.arange(24).reshape(6,4)
>>> x
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11],
       [12, 13, 14, 15],
       [16, 17, 18, 19],
       [20, 21, 22, 23]])

现在我需要的是:

array([[12,  9,  6,  3],
       [16, 13, 10,  7],
       [20, 17, 14, 11]])

所以我有一组(固定)列索引。行索引取决于它们。例如:row = col-1:col+1

有没有一种有效的方法呢?我知道我可以从每一列迭代并切片我需要的条目,但对我来说效率似乎非常低。

2 个答案:

答案 0 :(得分:4)

您可以使用as_strided执行此操作:

In [1]: from numpy.lib.stride_tricks import as_strided
In [2]: sz = x.itemsize
In [3]: d = as_strided(x[-1::-1,:], shape=(3,4), strides=sz*np.array([-4,-3]))
In [4]: d
Out[5]: 
array([[20, 17, 14, 11],
       [16, 13, 10,  7],
       [12,  9,  6,  3]])

也就是说,从原始数组倒置开始,填充一个3x4数组,其中第一个坐标向后跨越4个项目,第二个坐标向后跨越3个项目。

如果需要,您可以反复查看d

In [6]: d[-1::-1,:]    # or np.flipud(d)
Out[6]: 
array([[12,  9,  6,  3],
       [16, 13, 10,  7],
       [20, 17, 14, 11]])

答案 1 :(得分:2)

我打算在评论中留下基于diagonal的解决方案,但在时间测试中证明它比strided更快。

In [128]: timeit d = as_strided(x[::-1,:], shape=(3,4),
     strides=sz*np.array([-4,-3]))[::-1,:]
10000 loops, best of 3: 44 µs per loop

In [129]: timeit np.array([x[::-1,:].diagonal(i) for i in [-2,-1,0]])
10000 loops, best of 3: 25.9 µs per loop

如果x更大,这可能不会成真。但diagonal解决方案的优势在于它可能更容易理解。


表示(69,40) x

np.array([x[::-1,:].diagonal(i) for i in range(-(n-1),1)])

生成一个(30,40)数组,其中包含所有长度为40的反向对角线。

as_strided解决方案是:

as_strided(x[::-1,:], shape=(n,m), strides=-sz*np.array([m,m-1]))[::-1,:]

要弄清楚如何调整值以产生正确的步幅并不容易。但它更快。时间与较小的数组基本相同,而diagonal方法随着大小减慢。