Supposons que vous ayez un tableau numpy et une liste:
>>> a = np.array([1,2,2,1]).reshape(2,2)
>>> a
array([[1, 2],
[2, 1]])
>>> b = [0, 10]
Je voudrais 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 jette une erreur:
ValueError: assignment destination is read-only
Je suppose que c'est parce que je ne peux pas vraiment écrire dans un tableau numpy.
P.S. La taille réelle du tableau numpy est de 514 par 504 et de la liste est de 8.
Au lieu de remplacer les valeurs une par une, il est possible de remapper tout le tableau comme suit:
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 crédit pour l'idée ci-dessus va à @ JoshAdel . C'est nettement plus rapide que ma réponse d'origine:
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 __== '__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
Eh bien, je suppose que ce dont vous avez besoin est
a[a==2] = 10 #replace all 2's with 10's
Un tableau en lecture seule dans numpy peut être rendu accessible en écriture:
nArray.flags.writeable = True
Ceci permettra alors des opérations d’affectation comme celle-ci:
nArray[nArray == 10] = 9999 # replace all 10's with 9999's
Le vrai problème n’était pas l’affectation elle-même, mais le drapeau en écriture.
Vous pouvez également utiliser np.choose(idx, vals)
, où idx
est un tableau d'indices indiquant la valeur de vals
à mettre à leur place. Les indices doivent cependant être basés sur 0. Assurez-vous également que idx
a un type de données entier. Donc, il vous suffira de faire:
np.choose(a.astype(np.int32) - 1, b)
J'ai trouvé une autre solution avec la fonction numpy place
. (Documentation ici )
En l'utilisant 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]])
Je n'ai pas pu définir les indicateurs ni utiliser un masque pour modifier la valeur. En fin de compte, je viens de faire une copie du tableau.
a2 = np.copy(a)