Могу ли я получить представление о массиве numpy в указанных индексах? (вид из "фантазии индексации" )

То, что мне нужно, - это способ получить "причудливую индексацию" (y = x [[0, 5, 21]]), чтобы вернуть представление вместо копии.

У меня есть массив, но я хочу иметь возможность работать с подмножеством этого массива (указанным в списке индексов) таким образом, что изменения в этом подмножестве также помещаются в нужные места в большом массив. Если я просто хочу что-то сделать с помощью первых 10 элементов, я могу просто использовать регулярную нарезку y = x [0:10]. Это отлично работает, потому что регулярная нарезка возвращает представление. Проблема в том, что я не хочу 0:10, но произвольный набор индексов.

Есть ли способ сделать это?

Ответ 1

Я не думаю, что есть способ обойти это. Я понимаю, что "причудливое индексирование" всегда будет возвращать копию. Лучшее решение, о котором я могу думать, это манипулировать y, а затем использовать те же самые причудливые индексы, чтобы впоследствии изменить значения x:

ii = [0, 5, 21]
y = x[ii]
<manipulate y>
x[ii] = y

Ответ 2

Вы можете просто сделать:

y = x[[0,1,4]]
func(y)
x[[0,1,4]] = y

Я не думаю, что вы можете получить представление с фантастическим индексированием. Возможно, вы этого не захотите, так как я думаю, что причудливое индексирование происходит довольно медленно, нужно просто скопировать данные один раз.

Ответ 3

Вот возможный способ симулировать наличие представления (некоторый синтаксический сахар), избегая явных операторов копирования в конце, используя "причудливый контекст представления". Вам нужно будет позаботиться о том, чтобы ваш код не изменял индексный массив в контексте

import contextlib

@contextlib.contextmanager
def fancy_index_view(arr, inds):
    # create copy from fancy inds
    arr_copy = arr[inds]

    # yield 'view' (copy)
    yield arr_copy

    # after context, save modified data
    arr[inds] = arr_copy

теперь, фрагмент

import numpy as np
foo = np.random.random((22,2))
row_inds = [0,5,21]
barview = foo[row_inds]
barview[::] = 1
foo[row_inds] = barview

можно заменить на

import numpy as np
foo = np.random.random((22,2))
row_inds = [0,5,21]
with fancy_index_view(foo, row_inds) as barview:
    barview[::] = 1

Ответ 4

Теоретически вы можете создать объект, который выполняет роль "причудливого представления" в другом массиве, и я могу придумать множество вариантов использования. Проблема в том, что такой объект не был бы совместим со стандартным механизмом numpy. Весь скомпилированный код с числовым кодом C зависит от доступности данных как внутреннего продукта показателей и индексов. Обобщение этого кода на принципиально разные форматы компоновки данных было бы гигантским делом. Для проекта, который пытается взять вызов в этом направлении, проверьте континуум Blaze.