Remplacer les valeurs d'un tableau d'index numpy par les valeurs d'une liste

supposons que vous ayez un tableau nummpy et une liste:

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

j'aimerais remplacer les valeurs dans un tableau, de sorte que 1 soit remplacé par 0, et 2 par 10.

j'ai trouvé un problème similaire ici - http://mail.python.org/pipermail//tutor/2011-September/085392.html

Mais en utilisant cette solution:

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

me Lance une erreur:

ValueError: assignment destination is read-only

je suppose que c'est parce que je ne peux pas vraiment écrire dans un numpy array.

P. La taille réelle du tableau numpy est 514 par 504 et de la liste est de 8.

17
demandé sur jns 2012-11-27 00:17:17

5 réponses

au lieu de remplacer les valeurs un par un, il est possible de refaire le tableau entier comme ceci:

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))

les rendements

[[ 0 10]
 [10  0]]

le mérite de l'idée ci-dessus revient à @ JoshAdel. Il est nettement plus rapide que ma réponse originale à cette question:

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())

j'ai comparé les deux versions de cette façon:

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
16
répondu unutbu 2017-05-23 12:34:47

Eh bien, je suppose que ce dont vous avez besoin est

a[a==2] = 10 #replace all 2's with 10's
30
répondu alex_jordan 2012-11-26 20:19:31

Lecture seule matrice dans numpy peut être rendue accessible en écriture:

nArray.flags.writeable = True

cela permettra alors des opérations d'assignation comme celle-ci:

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

le vrai problème n'était pas l'assignation elle-même mais le drapeau inscriptible.

20
répondu DorinPopescu 2015-10-29 10:05:51

j'ai trouvé une autre solution avec la fonction numpy place. (Documentation ici)

Utiliser sur votre exemple:

>>> 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]])
0
répondu Linda 2017-01-12 14:44:32

vous pouvez aussi utiliser np.choose(idx, vals), où idx est un tableau d'indices qui indiquent la valeur de vals devrait être mis à leur place. Les indices doivent être basés sur 0. Assurez-vous également que idx a un type de données entier. Donc, vous n'aurez qu'à faire:

np.choose(a.astype(np.int32) - 1, b)
0
répondu jns 2017-11-29 20:02:11