假设我在Python中使用numpy并且我有一个任意大小的二维数组。为方便起见,假设我有一个5 x 5阵列。具体数字对我的问题不是特别重要;他们只是一个例子。
a = numpy.arrange(25).reshape(5,5)
这会产生:
[[0, 1, 2, 3, 4 ],
[5, 6, 7, 8, 9 ],
[10,11,12,13,14],
[15,16,17,18,19],
[20,21,22,23,24]]
现在,假设我想拍摄此阵列的2D切片。在正常情况下,这很容易。为了让细胞紧邻2,2,我只需使用a[1:4,1,4]
即可产生预期的
[[6, 7, 8 ],
[11, 12, 13],
[16, 17, 18]]
但是,如果我想采取一个包裹的切片怎么办?
在阵列的边缘?例如a[-1:2,-1:2]
将产生:
[24, 20, 21],
[4, 0, 1 ],
[9, 5, 6 ]
这在边缘无关紧要的几种情况下很有用,例如围绕屏幕的游戏图形。我意识到这可以通过很多if语句和边界检查来完成,但我想知道是否有更简洁,更惯用的方法来实现这一点。
环顾四周,我找到了几个答案:https://stackoverflow.com/questions/17739543/wrapping-around-slices-in-python-numpy适用于一维数组,但我还没有弄清楚如何将这个逻辑应用于2D切片。
基本上,问题是:如何在numpy中包围数组边缘的2D数组的2D切片?
提前感谢任何可以提供帮助的人。
答案 0 :(得分:12)
这适用于numpy> = 1.7。
a = np.arange(25).reshape(5,5)
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, 24]])
pad例程有一个'wrap'方法......
b = np.pad(a, 1, mode='wrap')
array([[24, 20, 21, 22, 23, 24, 20],
[ 4, 0, 1, 2, 3, 4, 0],
[ 9, 5, 6, 7, 8, 9, 5],
[14, 10, 11, 12, 13, 14, 10],
[19, 15, 16, 17, 18, 19, 15],
[24, 20, 21, 22, 23, 24, 20],
[ 4, 0, 1, 2, 3, 4, 0]])
根据具体情况,您可能需要为任意切片的每个术语添加1,以便考虑b
周围的填充。
答案 1 :(得分:10)
在使用各种方法一段时间之后,我只是找到了一个使用ndarray.take
工作的相当简单的解决方案。使用我在问题中提供的示例:
a.take(range(-1,2),mode='wrap', axis=0).take(range(-1,2),mode='wrap',axis=1)
提供所需的
输出[[24 20 21]
[4 0 1]
[9 5 6]]
事实证明它比我想象的要简单得多。如果您反转两个轴,此解决方案也适用。
这与我之前使用take
看到的答案类似,但我还没有看到有人解释过它之前是如何与2D数组一起使用的,所以我寄希望于此它可以帮助将来有同样问题的人。
答案 2 :(得分:1)
您也可以使用roll
来滚动数组然后剪切:
b = np.roll(np.roll(a, 1, axis=0), 1, axis=1)[:3,:3]
给出
array([[24, 20, 21],
[ 4, 0, 1],
[ 9, 5, 6]])
答案 3 :(得分:1)
我在使用环绕式索引时遇到了类似的挑战,只有在我的情况下,我需要在原始矩阵中设置值。我通过'花式索引'并使用meshgrid函数解决了这个问题:
A = arange(25).reshape((5,5)) # destinatoin matrix
print 'A:\n',A
k =-1* np.arange(9).reshape(3,3)# test kernel, all negative
print 'Kernel:\n', k
ix,iy = np.meshgrid(arange(3),arange(3)) # create x and y basis indices
pos = (0,-1) # insertion position
# create insertion indices
x = (ix+pos[0]) % A.shape[0]
y = (iy+pos[1]) % A.shape[1]
A[x,y] = k # set values
print 'Result:\n',A
输出:
A:
[[ 0 1 2 3 4]
[ 5 6 7 8 9]
[10 11 12 13 14]
[15 16 17 18 19]
[20 21 22 23 24]]
Kernel:
[[ 0 -1 -2]
[-3 -4 -5]
[-6 -7 -8]]
Result:
[[-3 -6 2 3 0]
[-4 -7 7 8 -1]
[-5 -8 12 13 -2]
[15 16 17 18 19]
[20 21 22 23 24]]
答案 4 :(得分:0)
正如我在评论中所提到的,How do I select a window from a numpy array with periodic boundary conditions?
有一个很好的答案这是另一种简单的方法
# First some setup
import numpy as np
A = np.arange(25).reshape((5, 5))
m, n = A.shape
然后
A[np.arange(i-1, i+2)%m].reshape((3, -1))[:,np.arange(j-1, j+2)%n]
获取可以分配的内容有点困难。 这是一个有点慢的版本。 为了获得类似的值,我将不得不这样做
A.flat[np.array([np.arange(j-1,j+2)%n+a*n for a in xrange(i-1, i+2)]).ravel()].reshape((3,3))
为了赋予它,我必须避免调用重新整形并直接使用由花式索引返回的展平版本。 这是一个例子:
n = 7
A = np.zeros((n, n))
for i in xrange(n-2, 0, -1):
A.flat[np.array([np.arange(i-1,i+2)%n+a*n for a in xrange(i-1, i+2)]).ravel()] = i+1
print A
返回
[[ 2. 2. 2. 0. 0. 0. 0.]
[ 2. 2. 2. 3. 0. 0. 0.]
[ 2. 2. 2. 3. 4. 0. 0.]
[ 0. 3. 3. 3. 4. 5. 0.]
[ 0. 0. 4. 4. 4. 5. 6.]
[ 0. 0. 0. 5. 5. 5. 6.]
[ 0. 0. 0. 0. 6. 6. 6.]]