有一個使用np.put, 及其'clip'選項的解決方案。它只需要一點技巧,因為該函數需要扁平矩陣中的索引;幸運的是,該功能np.ravel_multi_index完成了這項工作:
import itertools
import numpy as np
x, y, z = 2, 0, 4
positions_matrix = np.zeros((100,100,100))
indices = np.array( list( itertools.product( (x-1, x, x+1), (y-1, y, y+1), (z-1, z, z+1)) ))
flat_indices = np.ravel_multi_index(indices.T, positions_matrix.shape, mode='clip')
positions_matrix.put(flat_indices, 1+positions_matrix.take(flat_indices))
# positions_matrix[2,1,4] is now 1.0
這個解決方案的好處是您可以使用其他模式,例如'wrap'(如果您的代理住在甜甜圈上;-) 或周期性空間)。
我將解釋它如何在較小的 2D 矩陣上工作:
import itertools
import numpy as np
positions_matrix = np.zeros((8,8))
ones = np.ones((3,3))
x, y = 0, 4
indices = np.array( list( itertools.product( (x-1, x, x+1), (y-1, y, y+1) )))
# array([[-1, 3],
# [-1, 4],
# [-1, 5],
# [ 0, 3],
# [ 0, 4],
# [ 0, 5],
# [ 1, 3],
# [ 1, 4],
# [ 1, 5]])
flat_indices = np.ravel_multi_index(indices.T, positions_matrix.shape, mode='clip')
# array([ 3, 4, 5, 3, 4, 5, 11, 12, 13])
positions_matrix.put(flat_indices, ones, mode='clip')
# positions_matrix is now:
# array([[0., 0., 0., 1., 1., 1., 0., 0.],
# [0., 0., 0., 1., 1., 1., 0., 0.],
# [0., 0., 0., 0., 0., 0., 0., 0.],
# [ ...
順便說一句,在這種情況下mode='clip'是多余的put。
好吧,我只是作弊put做作業。+=1需要take和put:_
positions_matrix.put(flat_indices, ones.flat + positions_matrix.take(flat_indices))
# notice that ones has to be flattened, or alternatively the result of take could be reshaped (3,3)
# positions_matrix is now:
# array([[0., 0., 0., 2., 2., 2., 0., 0.],
# [0., 0., 0., 2., 2., 2., 0., 0.],
# [0., 0., 0., 0., 0., 0., 0., 0.],
# [ ...
與其他解決方案相比,此解決方案有一個重要區別:ones矩陣始終為 (3,3),這可能是優勢,也可能不是優勢。訣竅就在這個 flat_indices 列表中,它有重復的條目(剪輯的結果)。
因此,如果您在最大索引處添加非常數子矩陣,則可能需要采取一些預防措施:
x, y = 1, 7
values = 1 + np.arange(9)
indices = np.array( list( itertools.product( (x-1, x, x+1), (y-1, y, y+1) )))
flat_indices = np.ravel_multi_index(indices.T, positions_matrix.shape, mode='clip')
positions_matrix.put(flat_indices, values, mode='clip')
# positions_matrix is now:
# array([[0., 0., 0., 2., 2., 2., 1., 3.],
# [0., 0., 0., 2., 2., 2., 4., 6.],
# [0., 0., 0., 0., 0., 0., 7., 9.],
...您可能期望最后一列是 2 5 8。目前,您可以處理flat_indices,例如通過放置-1越界位置。但是,如果np.put接受非平面索引,或者如果有一個 clip ,這一切都會更容易mode='ignore'。