Как манипулировать элементами массива numpy, используя массив индексов диапазона (начальный индекс, конечный индекс)?

avatar
ARK1375
9 августа 2021 в 05:23
155
2
0

У меня есть простой одномерный массив NumPy с именем ar1 и другой массив, который показывает индексы диапазона (начальный индекс, конечный индекс) ar1 с именем idx. Структура выглядит примерно так:

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

Теперь я хочу изменить элементы в ar1, используя индексы диапазона, которые у меня есть в idx. Другими словами, я ищу эффективный способ использования функций и приемов Numpy для управления ar1 от 1 до 10, <66605952996060588>60 до 66 и от 100 до 110 элементов и, например, установить для них число 255.
Как мне это сделать?

Источник
hpaulj
9 августа 2021 в 05:53
2

Просто сделайте очевидный неэффективный способ. Либо повторяйте выполнение нескольких срезов, либо объединяйте несколько диапазонов в один список индексов. Ломтики различаются по размеру, поэтому нет никакого волшебного способа сделать их все сразу.

Axiomel
9 августа 2021 в 05:55
0

Думаю, я соглашусь с hpaulj, что нет более эффективного способа сделать это, чем фактически сгенерировать все индексы.

ARK1375
9 августа 2021 в 05:55
0

@hpaulj Объединение разных диапазонов с использованием np.arange() на самом деле было первым решением, которое пришло мне в голову, но я подумал, что должен быть более эффективный способ сделать это. Вот почему я задал вопрос.

hpaulj
9 августа 2021 в 06:50
1

Невозможно сделать несколько срезов «все сразу». Срез — это простой регулярный шаблон, выражаемый тремя значениями — старт/стоп/шаг.

Ответы (2)

avatar
Suneesh Jacob
9 августа 2021 в 05:55
1
for i in range(len(idx)):
    ar1[idx[i][0]-1:idx[i][1]].fill(255)
avatar
Axiomel
9 августа 2021 в 05:54
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
hpaulj
9 августа 2021 в 06:44
0

indices=np.concatenate([np.arange(i,j) for i,j in all_ranges]) должно быть лучше, чем повторяющийся +=. + подходит для объединения нескольких списков, но относительно медленно, если выполняется повторно или для многих списков.