Подтвердить что ты не робот

Заменить значения массива индекса numpy со значениями списка

Предположим, у вас есть массив numpy и список:

>>> a = np.array([1,2,2,1]).reshape(2,2)
>>> a
array([[1, 2],
       [2, 1]])
>>> b = [0, 10]

Я хочу заменить значения в массиве, так что 1 заменяется на 0 и 2 на 10.

Я нашел аналогичную проблему здесь - http://mail.python.org/pipermail//tutor/2011-September/085392.html

Но используя это решение:

for x in np.nditer(a):
    if x==1:
        x[...]=x=0
    elif x==2:
        x[...]=x=10

Выдает мне сообщение об ошибке:

ValueError: assignment destination is read-only

Я предполагаю, что из-за того, что я не могу писать в массив numpy.

P.S. Фактический размер массива numpy равен 514 на 504, а списка - 8.

4b9b3361

Ответ 1

Вместо замены значений один за другим можно переназначить весь массив следующим образом:

import numpy as np
a = np.array([1,2,2,1]).reshape(2,2)
# palette must be given in sorted order
palette = [1, 2]
# key gives the new values you wish palette to be mapped to.
key = np.array([0, 10])
index = np.digitize(a.ravel(), palette, right=True)
print(key[index].reshape(a.shape))

дает

[[ 0 10]
 [10  0]]

Кредит для вышеупомянутой идеи - @JoshAdel. Это значительно быстрее, чем мой первоначальный ответ:

import numpy as np
import random
palette = np.arange(8)
key = palette**2
a = np.array([random.choice(palette) for i in range(514*504)]).reshape(514,504)

def using_unique():
    palette, index = np.unique(a, return_inverse=True)
    return key[index].reshape(a.shape)

def using_digitize():
    index = np.digitize(a.ravel(), palette, right=True)
    return key[index].reshape(a.shape)

if __name__ == '__main__':
    assert np.allclose(using_unique(), using_digitize())

Я сравнивал две версии таким образом:

In [107]: %timeit using_unique()
10 loops, best of 3: 35.6 ms per loop
In [112]: %timeit using_digitize()
100 loops, best of 3: 5.14 ms per loop

Ответ 2

Ну, я полагаю, что вам нужно

a[a==2] = 10 #replace all 2 with 10's

Ответ 3

Массив только для чтения в numpy может быть доступен для записи:

nArray.flags.writeable = True

Затем будут разрешены операции присваивания, такие как:

nArray[nArray == 10] = 9999 # replace all 10 with 9999's

Реальной проблемой было не само присваивание, а флаг записи.

Ответ 4

Я нашел другое решение с функцией numpy place. (Документация здесь)

Используя его в вашем примере:

>>> a = np.array([1,2,2,1]).reshape(2,2)
>>> a
array([[1, 2],
   [2, 1]])
>>> np.place(a, a==1, 0)
>>> np.place(a, a==2, 10)
>>> a
array([[ 0, 10],
       [10,  0]])

Ответ 5

Вы также можете использовать np.choose(idx, vals), где idx - это массив индексов, указывающий, какое значение vals должно быть помещено на их место. Однако индексы должны быть основаны на 0. Также убедитесь, что idx имеет целочисленный тип данных. Поэтому вам нужно будет только:

np.choose(a.astype(np.int32) - 1, b)