2017-08-10 3 views
2

Dans un tableau numéroté, je souhaite remplacer tous les nan et inf par un nombre fixe. Puis-je faire cela en une seule étape pour gagner du temps de calcul (les tableaux sont vraiment gros)?python: masquage combiné en numpy

a = np.arange(10.0) 
a[3] = np.nan 
a[5] = np.inf 
a[7] = -np.inf 
# a: [ 0. 1. 2. nan 4. inf 6. -inf 8. 9.] 

a[np.isnan(a)] = -999 
a[np.isinf(a)] = -999 
# a: [ 0. 1. 2. -999. 4. -999. 6. -999. 8. 9.] 

Le code ci-dessus fonctionne correctement. Mais je cherche quelque chose comme:

a[np.isnan(a) or np.isinf(a)] = -999 

Ce qui ne fonctionne pas et je peux voir pourquoi. Juste en pensant qu'il pourrait être mieux si chaque élément d'un est seulement vérifié une fois.

Répondre

2

cela semble fonctionner:

a[np.isnan(a) | np.isinf(a)] = 2 

np.isnan() et np.isinf() en fait revenir deux tableaux de numpy booléens.

Les tableaux de nombres booléens peuvent être combinés avec des opérations de bits comme & et |

+0

Magnifique! Quelle est la différence entre "ou" et "|"? Peut-être la logique bit à bit? En passant, je viens de le tester: la version combinée est grossièrement 10% plus rapide. Edit: Ok, je vois. Merci! – offeltoffel

3

Numpy est livré avec sa propre version vectorisée ou:

a[np.logical_or(np.isnan(a), np.isinf(a))] = -999 

Alors que la version ci-dessus est understanable claire, il y a une plus rapide, ce qui est un peu bizarre:

a[np.isnan(a-a)] = -9999 

L'idée derrière cela est que « np.inf-np.inf = np.nan`

%timeit a[np.isnan(a-a)] = -999 
# 100000 loops, best of 3: 11.7 µs per loop 
%timeit a[np.isnan(a) | np.isinf(a)] = -999 
# 10000 loops, best of 3: 51.4 µs per loop 
%timeit a[np.logical_or(np.isnan(a), np.isinf(a))] = -999 
# 10000 loops, best of 3: 51.4 µs per loop 

D'où la | et la version np.logical_or semblent être interne équivalente

+1

numpy est une chose miraculeuse – offeltoffel

3

Vous pouvez utiliser np.isfinite qui vérifie qu'un certain nombre n'est pas infini, ni un NaN:

a[~np.isfinite(a)] = -999 
+0

Ça a l'air bien aussi! Qu'est-ce que ~ fait? – offeltoffel

+1

'~' est logique * pas *. –