np.nditer не присваивает значения, когда перебирает подмассив - PullRequest
0 голосов
/ 13 октября 2019

Основной массив не обновляет значения при назначении метода внутри np.nditer , когда в качестве подмассива используется итеративный массив

array = np.arange(20)

with np.nditer(array[np.nonzero(array)],
               op_flags=['readwrite']) as it:
    for x in it:
        x[...] = 5
array

([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19])


Назначения подмассиваотлично без np.nditer

array[np.nonzero(array)] = 5
array

массив ([0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,5, 5, 5, 5, 5, 5, 5, 5])


Существует обходной путь с использованием временного массива.

tmp_array = array[np.nonzero(array)]

array = np.arange(20)

with np.nditer(tmp_array,
               op_flags=['readwrite']) as it:
    for x in it:
        x[...] = 5

array[np.nonzero(array)] = tmp_array
array

массив ([0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5])

  1. Почему основной массив не обновляет значения, когда np.nditer использует назначения подмассива?
  2. Есть ли более удобный способ обойти, когда происходит подрешетка в np.nditer ?

1 Ответ

1 голос
/ 13 октября 2019
In [48]: arr = np.arange(20) 
    ...: with np.nditer(arr[np.nonzero(arr)], 
    ...:                op_flags=['readwrite']) as it: 
    ...:     for x in it: 
    ...:         x[...] = 5 
    ...: arr                                                                    
Out[48]: 
array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16,
       17, 18, 19])

Это не меняет arr, потому что оно не повторяется на arr. Вместо этого он делает:

In [49]: arr = np.arange(20) 
    ...: arr1 = arr[np.nonzero(arr)] 
    ...: with np.nditer(arr1, 
    ...:                op_flags=['readwrite']) as it: 
    ...:     for x in it: 
    ...:         x[...] = 5 
    ...: arr1                                                                   
Out[49]: array([5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5])
In [50]: _.shape                                                                
Out[50]: (19,)

arr1 не view из arr, это выборка, новый массив без общего буфера данных.

Если вы хотитечтобы изменить arr, вы должны выполнить итерацию, а не копию. Проведите тест или что-нибудь необычное внутри цикла.

In [51]: arr = np.arange(20) 
    ...: with np.nditer(arr, 
    ...:                op_flags=['readwrite']) as it: 
    ...:     for x in it: 
    ...:         if x > 0: 
    ...:             x[...] = 5 
    ...: arr                                                                    
Out[51]: array([0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5])

Но почему вы используете nditer? Вы уже знаете, как выполнить выборочное присваивание такого рода, используя неитерационные методы:

array[np.nonzero(array)] = 5

. В этом случае присваивание = следует сразу за расширенным индексированием, а Python использует array.__setitem__ вместоarr.__getitem__.

Итерируя по срезу, view меняет источник:

In [52]: arr = np.arange(20) 
    ...: with np.nditer(arr[5:], 
    ...:                op_flags=['readwrite']) as it: 
    ...:     for x in it: 
    ...:         x[...] = 5 
    ...: arr                                                                    
Out[52]: array([0, 1, 2, 3, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...