Различное поведение индексации и нарезки в numpy структурированных массивах - PullRequest
1 голос
/ 24 апреля 2020

Предположим, у вас есть структурированный массив a:

import numpy as np

a = np.array([1, 2, 3, 4, 5, 6], dtype=[('val', 'i4')])
print(a)
[(1,) (2,) (3,) (4,) (5,) (6,)]

Теперь, если я хочу изменить одну из записей на другое значение, следующие два способа кажутся эквивалентными ( Случай I ):

# both of these work
"""version a)"""
a['val'][1] = 10
print(a)
[( 1,) (10,) ( 3,) ( 4,) ( 5,) ( 6,)]

"""version b)"""
a[1]['val'] = 2
print(a)
[(1,) (2,) (3,) (4,) (5,) (6,)]

Но эта двусмысленность (не уверен, что это правильный термин) сломается, если мы попытаемся изменить более одной записи ( Случай II ):

"""version a)"""
a['val'][[0, 1]] = 15
print(a)
[(15,) (15,) ( 3,) ( 4,) ( 5,) ( 6,)]
# this works

"""version b)"""
a[[0, 1]]['val'] = 5
print(a)
[(15,) (15,) ( 3,) ( 4,) ( 5,) ( 6,)]
# this has no effect

Я подумал, что, возможно, во втором случае, версия b), создается новый объект, поэтому назначение нового значения этим записям влияет только на новый объект, но не на исходный. Но и в первом случае, версия b), создается новый объект, так как оба следующих оператора возвращают False:

print(a[1]['val'] is a['val'][1])
print(a['val'][[0, 1]] is a[[0, 1]]['val'])

Тот факт, что эта неопределенность дается только в первом Случай, но не второй, кажется мне противоречивым, хотя бы сбивающим с толку. Чего мне не хватает?

1 Ответ

1 голос
/ 24 апреля 2020

Отличное наблюдение. За numpy do c: Для всех случаев индексных массивов возвращается копия исходных данных, а не представление, полученное для срезов. В то время как индексирование по одному элементу возвращает представление.

Также обратите внимание, что согласно scipy do c, вызывающие поля в структурированных массивах создают представление, а также индексация с целым числом создает структурированный скаляр, для которого в отличие от других numpy скаляров, структурированные скаляры являются изменяемыми и действуют как представления в исходный массив, так что изменение скаляра изменит исходный массив. Структурированные скаляры также поддерживают доступ и присваивание по имени поля

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...