我找不到任何关于我想做什么的问题,所以我现在就问。基本上,我想在矩阵中切片,其中行索引取决于列索引。
例如:
>>> 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
有没有一种有效的方法呢?我知道我可以从每一列迭代并切片我需要的条目,但对我来说效率似乎非常低。
答案 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
方法随着大小减慢。