展开NumPy索引选择

dly7yett  于 2022-11-10  发布在  其他
关注(0)|答案(3)|浏览(135)

假设我有一个NumPy数组x和索引idx

x = np.ones(20)
idx = np.array([1, 2, 10, 19])

对于这些索引,如果我希望将x的值设置为零,则可以执行以下操作:

x[idx] = 0

但是,对于这些索引中的每一个,我也想将它们的m邻居设置为零(请注意,m < 0指的是索引左侧的m邻居,m > 0指的是索引右侧的m邻居)。天真地说,我可以这样做:


# Note this example only works when `m > 0`

m = 3
for i in idx:
    x[i:i+m] = 0

array([1., 0., 0., 0., 0., 1., 1., 1., 1., 1., 0., 0., 0., 1., 1., 1., 1., 1., 1., 0.])

xidx都非常、非常长时,避免或改进此for循环性能的最佳方法是什么?

更新

实际上,len(x)100_000_000len(idx)10_000。我需要在不到一秒的时间内执行这个命令。

r7xajy2e

r7xajy2e1#

我想到的是:创建一个受影响的索引的组合列表。然后将其修剪为原始数组的大小。然后访问该阵列。

idx1 = np.unique(np.concatenate([idx+i for i in range(m + 1)]))
idx1 = idx1[(0 <= idx1) & (idx1 < x.shape)]
x[idx1] = 0
vltsax25

vltsax252#

import numpy as np

x = np.ones(20)
idx = np.array([1, 2, 10, 19])
ranges = [np.arange(a, b+1) for a, b in zip(idx-1, idx+1)]
ranges = np.array(ranges)
ranges = np.clip(ranges, 0, len(x)-1)
x[ranges] = 0
print(x)

产出

array([0., 0., 0., 0., 1., 1., 1., 1., 1., 0., 0., 0., 1., 1., 1., 1., 1., 1., 0., 0.])

1.对idx的每个元素使用zip创建包含+1和-1的np.array
1.由于可能存在超出/低于x范围的值,请使用np.clip将它们放入允许的索引中
1.现在您可以像使用索引一样使用创建的数组

iyfjxgzm

iyfjxgzm3#

我认为numpy.linspace在这里很有用。重要的是要将“Endpoint”选项设置为False,以避免交叉链接范围。

def func1(a, idx, m):
    idx_ext = np.linspace(idx - 1 , idx + m - 1, m, endpoint = False).astype(int)
    a[idx_ext.ravel()] = 0
    return a

对于大型数组,执行时间不是很长:

%timeit func1 (np.arange(100_000_000),np.tile(idx,10_000),m)
500 ms ± 8.73 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

相关问题