【问题标题】:How to manipulate a numpy array's elements using an array of range (start index, end index) indices?如何使用范围(开始索引,结束索引)索引数组操作 numpy 数组的元素?
【发布时间】:2021-10-12 20:37:11
【问题描述】:

我有一个简单的一维 NumPy 数组,名为 ar1,另一个数组显示了 ar1 的范围索引(开始索引,结束索引),名为 idx。结构看起来像这样:

ar1 = np.zeros((m*n))   
idx = np.array(
    [[1,10],
     [40,80],
     [100,110]] )

现在我想使用idx 中的范围索引更改ar1 中的元素。换句话说,我正在寻找一种有效的方法,使用 Numpy 函数和技巧来操纵ar11 到 1040 到 80 和 100 到 110 元素,例如,将它们设置为数字 255。
我该怎么做?

【问题讨论】:

  • 只做明显低效的方法。要么迭代做多个切片,要么将多个范围组合成一个索引列表。切片的大小不同,因此没有神奇的方法可以一次完成所有切片。
  • 我同意 hpaulj 的观点,即没有比实际生成所有索引更有效的方法了。
  • @hpaulj 使用np.arange() 组合不同的范围实际上是我想到的第一个解决方案,但我认为应该有更有效的方法来做到这一点。这就是我问这个问题的原因。
  • 没有一种方法可以“一次性”执行多个切片。切片是一种简单的常规模式,可以用 3 个值表示 - 开始/停止/步进。

标签: python numpy


【解决方案1】:

如果只生成一次所有所需的索引,那对您的应用程序来说会很慢吗?思考类似:

def generate_indices( all_ranges ):
    """Take a list of ranges and explicitly create all indices"""
    indices = []
    for sub_range in all_ranges:
        indices += range( sub_range[0], sub_range[1] ) 
    return np.array( indices )

然后你可以操作为

m=n=25
ar1 = np.zeros((m*n))   
idx = np.array(
    [[1,10],
     [40,80],
     [100,110]] )
indices = generate_indices( idx )
ar1[indices] = 255

【讨论】:

  • indices=np.concatenate([np.arange(i,j) for i,j in all_ranges]) 应该比重复的+= 更好。 + 可以加入几个列表,但在重复或多个列表时相对较慢。
【解决方案2】:
for i in range(len(idx)):
    ar1[idx[i][0]-1:idx[i][1]].fill(255)

【讨论】: