Python “查找全部”;“邻居”;对于多维数组中的元素,环绕边界

Python “查找全部”;“邻居”;对于多维数组中的元素,环绕边界,python,numpy,multidimensional-array,boundary,Python,Numpy,Multidimensional Array,Boundary,假设我使用2D/3D numpy阵列对由单元组成的长方体进行建模。单元格以从0开始递增的数字进行标记。在这之前,这可以通过 box = np.arange(np.prod(n_cells)) box = box.reshape(n_cells) 其中,n_cells是一个np.array,它存储框在每个维度中应该具有的单元数,基本上是以单元计的框的维度 现在,对我来说最困难的部分是找到一种智能的方法来找到每个细胞的邻居。我的目标是建立一个数组或列表,其中包含每个单元格的邻居-理想情况下,让我们

假设我使用2D/3D numpy阵列对由单元组成的长方体进行建模。单元格以从0开始递增的数字进行标记。在这之前,这可以通过

box = np.arange(np.prod(n_cells))
box = box.reshape(n_cells)
其中,
n_cells
是一个np.array,它存储框在每个维度中应该具有的单元数,基本上是以单元计的框的维度

现在,对我来说最困难的部分是找到一种智能的方法来找到每个细胞的邻居。我的目标是建立一个数组或列表,其中包含每个单元格的邻居-理想情况下,让我们看一个小的2D示例

0   1   2   3
4   5   6   7
8   9   10 11
12  13  14 15 
在这里,没有周期性边界条件,邻域是

0: 1, 4, 5
1: 0, 2, 4, 5, 6
2: 1, 5, 6, 7, 3
...
但我想用周期性的边界条件,这样

0: 1, 4, 5, 3, 7, 12, 13, 15
1: 0, 2, 4, 5, 6, 12, 13, 14
这样,每个元素在2D中都有8个邻居。 理想情况下,我希望能够为任何维度创建这样的列表/数组,但如果没有通用解决方案,我对2D/3D特别感兴趣

另一个问题,我必须解决的是,通过这种方式,我将所有对计数两次,即0是1的邻居,1是0的邻居。这是一个问题,我也需要解决,但这不是主要问题。

这可以通过沿给定轴“滚动”阵列来完成,完全是您想要的缠绕方式。例如,按(-1,-1)滚动会将所有内容向左和向上移动,因此数组变为

  [[ 5,  6,  7,  4],
   [ 9, 10, 11,  8],
   [13, 14, 15, 12],
   [ 1,  2,  3,  0]]
这样,我们就找到了每个点的东南邻居。要展平此列表(
ravel
),对9个偏移量中的每一个重复此过程(包括(0,0)表示数字本身),并叠加结果。该解决方案适用于数组
b
的任意维数:

dim = len(b.shape)       # number of dimensions
offsets = [0, -1, 1]     # offsets, 0 first so the original entry is first 
columns = []
for shift in itertools.product(offsets, repeat=dim):   # equivalent to dim nested loops over offsets
    columns.append(np.roll(b, shift, np.arange(dim)).ravel())
neighbors = np.stack(columns, axis=-1)
输出(相邻的
):

在每一行中,第一个条目是原始编号,其他条目是其邻居

要使每个条目邻居对只列出一次,可以屏蔽冗余条目,例如使用NaN:

np.where(neighbors >= neighbors[:, [0]], neighbors, np.nan)

  [[  0.,   1.,   3.,   4.,   5.,   7.,  12.,  13.,  15.],
   [  1.,   2.,  nan,   5.,   6.,   4.,  13.,  14.,  12.],
   [  2.,   3.,  nan,   6.,   7.,   5.,  14.,  15.,  13.],
   [  3.,  nan,  nan,   7.,   4.,   6.,  15.,  12.,  14.],
   [  4.,   5.,   7.,   8.,   9.,  11.,  nan,  nan,  nan],
   [  5.,   6.,  nan,   9.,  10.,   8.,  nan,  nan,  nan],
   [  6.,   7.,  nan,  10.,  11.,   9.,  nan,  nan,  nan],
   [  7.,  nan,  nan,  11.,   8.,  10.,  nan,  nan,  nan],
   [  8.,   9.,  11.,  12.,  13.,  15.,  nan,  nan,  nan],
   [  9.,  10.,  nan,  13.,  14.,  12.,  nan,  nan,  nan],
   [ 10.,  11.,  nan,  14.,  15.,  13.,  nan,  nan,  nan],
   [ 11.,  nan,  nan,  15.,  12.,  14.,  nan,  nan,  nan],
   [ 12.,  13.,  15.,  nan,  nan,  nan,  nan,  nan,  nan],
   [ 13.,  14.,  nan,  nan,  nan,  nan,  nan,  nan,  nan],
   [ 14.,  15.,  nan,  nan,  nan,  nan,  nan,  nan,  nan],
   [ 15.,  nan,  nan,  nan,  nan,  nan,  nan,  nan,  nan]])

其思想是,
neighbories>=neighbories[:,[0]]
只列出那些数字大于单元格本身的人。

像这样吗?还是这个?可能重复的Thx,这是我想要的方向,但它不涉及周期性。您可以使用
x%=len(维度)
来调整这些方法,如果x<0:x+=len(维度)
产品采用了一个重复的参数,这个参数稍微清晰一点,这是一种美!非常感谢你,这正是我用如此简洁的方式寻找的,并且很好地解释了。
np.where(neighbors >= neighbors[:, [0]], neighbors, np.nan)

  [[  0.,   1.,   3.,   4.,   5.,   7.,  12.,  13.,  15.],
   [  1.,   2.,  nan,   5.,   6.,   4.,  13.,  14.,  12.],
   [  2.,   3.,  nan,   6.,   7.,   5.,  14.,  15.,  13.],
   [  3.,  nan,  nan,   7.,   4.,   6.,  15.,  12.,  14.],
   [  4.,   5.,   7.,   8.,   9.,  11.,  nan,  nan,  nan],
   [  5.,   6.,  nan,   9.,  10.,   8.,  nan,  nan,  nan],
   [  6.,   7.,  nan,  10.,  11.,   9.,  nan,  nan,  nan],
   [  7.,  nan,  nan,  11.,   8.,  10.,  nan,  nan,  nan],
   [  8.,   9.,  11.,  12.,  13.,  15.,  nan,  nan,  nan],
   [  9.,  10.,  nan,  13.,  14.,  12.,  nan,  nan,  nan],
   [ 10.,  11.,  nan,  14.,  15.,  13.,  nan,  nan,  nan],
   [ 11.,  nan,  nan,  15.,  12.,  14.,  nan,  nan,  nan],
   [ 12.,  13.,  15.,  nan,  nan,  nan,  nan,  nan,  nan],
   [ 13.,  14.,  nan,  nan,  nan,  nan,  nan,  nan,  nan],
   [ 14.,  15.,  nan,  nan,  nan,  nan,  nan,  nan,  nan],
   [ 15.,  nan,  nan,  nan,  nan,  nan,  nan,  nan,  nan]])