如何在考虑边界的情况下获取numpy数组的邻近元素?

7 投票
4 回答
17898 浏览
提问于 2025-04-17 02:26

我想在numpy数组中获取某个元素的邻居。我们来看下面这个例子:

    a = numpy.array([0,1,2,3,4,5,6,7,8,9])

我想指定位置5,并想从两边各获取三个邻居。这是可以做到的。

   index = 5
   num_neighbor=3
   left = a[index-num_neighbor:index]
   right= a[num_neighbor+1:num_neighbor+index+1]

不过,上面的代码没有考虑到边界问题……我希望能在数组的边界内获取邻居。例如,如果索引是1,那么左边的邻居只有一个元素,就是0。

非常感谢!

4 个回答

1

我想到的方法是先把数组切分,然后根据需要填充一些超出范围的值。

这个内容来自于 这里

def surrounding(x, idx, radius=1, fill=0):
""" 
Gets surrounding elements from a numpy array 

Parameters: 
x (ndarray of rank N): Input array
idx (N-Dimensional Index): The index at which to get surrounding elements. If None is specified for a particular axis,
    the entire axis is returned.
radius (array-like of rank N or scalar): The radius across each axis. If None is specified for a particular axis, 
    the entire axis is returned.
fill (scalar or None): The value to fill the array for indices that are out-of-bounds.
    If value is None, only the surrounding indices that are within the original array are returned.

Returns: 
ndarray: The surrounding elements at the specified index
"""

assert len(idx) == len(x.shape)

if np.isscalar(radius): radius = tuple([radius for i in range(len(x.shape))])

slices = []
paddings = []
for axis in range(len(x.shape)):
    if idx[axis] is None or radius[axis] is None:
        slices.append(slice(0, x.shape[axis]))
        paddings.append((0, 0))
        continue

    r = radius[axis]
    l = idx[axis] - r 
    r = idx[axis] + r

    pl = 0 if l > 0 else abs(l)
    pr = 0 if r < x.shape[axis] else r - x.shape[axis] + 1

    slices.append(slice(max(0, l), min(x.shape[axis], r+1)))
    paddings.append((pl, pr))

if fill is None: return x[slices]
return np.pad(x[slices], paddings, 'constant', constant_values=fill)
17

在编程中,有时候我们会遇到一些问题,特别是在使用某些工具或库的时候。这些问题可能会让我们感到困惑,不知道该怎么解决。比如,有人可能在使用某个功能时,发现它没有按照预期工作,或者出现了错误信息。这时候,我们就需要去查找相关的资料,看看有没有人遇到过类似的问题,或者有没有解决方案。

在StackOverflow上,很多人会分享他们的经验和解决方法。你可以在这里找到很多有用的信息,帮助你理解问题的根源,以及如何解决它们。记得在提问时,尽量描述清楚你遇到的问题,这样别人才能更好地帮助你。

总之,遇到问题时不要慌,先查找资料,看看有没有人遇到过类似的情况,或者直接向社区求助,通常都会有解决办法的。

left = a[max(0,index-num_neighbor):index]
3
import numpy as np
a = np.array([0,1,2,3,4,5,6,7,8,9])
num_neighbor=3    

for index in range(len(a)):
    left = a[:index][-num_neighbor:]
    right= a[index+1:num_neighbor+index+1]
    print(index,left,right)

结果是

(0, array([], dtype=int32), array([1, 2, 3]))
(1, array([0]), array([2, 3, 4]))
(2, array([0, 1]), array([3, 4, 5]))
(3, array([0, 1, 2]), array([4, 5, 6]))
(4, array([1, 2, 3]), array([5, 6, 7]))
(5, array([2, 3, 4]), array([6, 7, 8]))
(6, array([3, 4, 5]), array([7, 8, 9]))
(7, array([4, 5, 6]), array([8, 9]))
(8, array([5, 6, 7]), array([9]))
(9, array([6, 7, 8]), array([], dtype=int32))

index<num_neighbor 时,a[index-num_neighbor:index] 不起作用的原因是因为切片规则的第3和第4条:

对于 s[i:j]

如果 i 或 j 是负数,那么这个索引是相对于字符串的末尾的:会用 len(s) + ilen(s) + j 来替代。

从 i 到 j 的切片定义为索引 k 的项的序列,满足 i <= k < j。如果 i 或 j 大于 len(s),就用 len(s)。如果 i 被省略或是 None,就用 0。如果 j 被省略或是 None,就用 len(s)。如果 i 大于或等于 j,切片就是空的。

所以当 index=1 时,a[index-num_neighbor:index] = a[-2:1] = a[10-2:1] = a[8:1] = []

撰写回答