如何在考虑边界的情况下获取NumPy数组中的相邻元素?

7
我想获取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个回答

17
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)+ i或len(s)+ j。

从i到j的s的片段被定义为具有索引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] = []


@unutbu... 你有没有想过如何在 Python 列表的多维情况下实现这个功能? - Shan
@Shan:你能给一个多维列表的例子和期望的输出吗?leftright的类比是什么? - unutbu

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)

-1

Python会为您处理边界问题:

>>> a = [0,1,2,3,4,5,6,7,8,9]
>>> a[-100 : 1000]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> a[-100:3]
[0, 1, 2]

2
只有当它为-100时才是有效的,例如-1、-2等将返回一个空数组。 - Shan
非常奇怪的行为。有什么解释吗? - Ilya Smagin
1
@Ilya Smagin:是的,这个问题是关于numpy数组而不是Python列表的。在numpy中,负索引表示从数组末尾开始向后索引。因此,在您的示例中,如果a是一个numpy数组,则a [0]将返回0,a [-1]将返回9。 - talonmies
@talonmies:你可以从一个普通的Python列表中取出一部分,得到相同的结果;range(5)[-100:3]返回[0, 1, 2]... 这有点出乎意料,因为你不能在列表或np.array中取任意大的负索引;range(5)[-100]会给出一个索引错误,np.array(range(5))[-100]也是如此。在这种情况下,你的负索引必须小于或等于列表长度的大小。 - Pat B

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接