Numpy:列相关切片
Numpy: Column dependent slicing
我找不到任何关于我想做什么的问题所以我现在问。基本上,我想在行索引取决于列索引的矩阵中进行切片。
例如:
>>> 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
有什么有效的方法吗?我知道我可以从每一列中迭代和切片我需要的条目,但对我来说这似乎效率很低。
您可以使用 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]])
也就是说,从原始数组倒置开始,通过第一个坐标向后移动 4 个项目,第二个坐标向后移动 3 个项目,填充一个 3x4 数组。
如果需要,您可以将 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]])
我打算在评论中留下一个基于 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
方法随着大小的增加而变慢。
我找不到任何关于我想做什么的问题所以我现在问。基本上,我想在行索引取决于列索引的矩阵中进行切片。
例如:
>>> 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
有什么有效的方法吗?我知道我可以从每一列中迭代和切片我需要的条目,但对我来说这似乎效率很低。
您可以使用 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]])
也就是说,从原始数组倒置开始,通过第一个坐标向后移动 4 个项目,第二个坐标向后移动 3 个项目,填充一个 3x4 数组。
如果需要,您可以将 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]])
我打算在评论中留下一个基于 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
方法随着大小的增加而变慢。