converter o valor nan para zero

97

Eu tenho uma matriz numpy 2D. Alguns dos valores nesta matriz são NaN. Quero realizar certas operações usando esta matriz. Por exemplo, considere a matriz:

[[   0.   43.   67.    0.   38.]
 [ 100.   86.   96.  100.   94.]
 [  76.   79.   83.   89.   56.]
 [  88.   NaN   67.   89.   81.]
 [  94.   79.   67.   89.   69.]
 [  88.   79.   58.   72.   63.]
 [  76.   79.   71.   67.   56.]
 [  71.   71.   NaN   56.  100.]]

Estou tentando pegar cada linha, uma de cada vez, classificá-la em ordem inversa para obter no máximo 3 valores da linha e tirar sua média. O código que tentei é:

# nparr is a 2D numpy array
for entry in nparr:
    sortedentry = sorted(entry, reverse=True)
    highest_3_values = sortedentry[:3]
    avg_highest_3 = float(sum(highest_3_values)) / 3

Isso não funciona para linhas contendo NaN. Minha pergunta é: existe uma maneira rápida de converter todos os NaNvalores para zero no array numpy 2D para que eu não tenha problemas com a classificação e outras coisas que estou tentando fazer.

Curious2learn
fonte
1
each: map: return isNaN(value) ? 0 : value
Kirilloid
@kirilloid: parece bom, que tal um exemplo de uso?
serv-inc

Respostas:

125

Isso deve funcionar:

from numpy import *

a = array([[1, 2, 3], [0, 3, NaN]])
where_are_NaNs = isnan(a)
a[where_are_NaNs] = 0

No caso acima, where_are_NaNs é:

In [12]: where_are_NaNs
Out[12]: 
array([[False, False, False],
       [False, False,  True]], dtype=bool)
Marcin
fonte
141

Onde Aestá o seu array 2D:

import numpy as np
A[np.isnan(A)] = 0

A função isnanproduz um array bool indicando onde NaNestão os valores. Um array booleano pode ser usado para indexar um array da mesma forma. Pense nisso como uma máscara.

Paulo
fonte
41

Que tal nan_to_num () ?

Drake Guan
fonte
11
nan_to_num () também muda infinitos - isso pode ser indesejado em alguns casos.
Agos
11
Também é> 10x mais lento do que os outros métodos.
user48956
7
Eu não tinha certeza sobre a declaração "> 10x lento", então verifiquei. Na verdade, é muito mais lento. Obrigado por apontar isso.
Gabriel
16

Você pode usar np.wherepara encontrar onde tem NaN:

import numpy as np

a = np.array([[   0,   43,   67,    0,   38],
              [ 100,   86,   96,  100,   94],
              [  76,   79,   83,   89,   56],
              [  88,   np.nan,   67,   89,   81],
              [  94,   79,   67,   89,   69],
              [  88,   79,   58,   72,   63],
              [  76,   79,   71,   67,   56],
              [  71,   71,   np.nan,   56,  100]])

b = np.where(np.isnan(a), 0, a)

In [20]: b
Out[20]: 
array([[   0.,   43.,   67.,    0.,   38.],
       [ 100.,   86.,   96.,  100.,   94.],
       [  76.,   79.,   83.,   89.,   56.],
       [  88.,    0.,   67.,   89.,   81.],
       [  94.,   79.,   67.,   89.,   69.],
       [  88.,   79.,   58.,   72.,   63.],
       [  76.,   79.,   71.,   67.,   56.],
       [  71.,   71.,    0.,   56.,  100.]])
Anton Protopopov
fonte
1
como está, não funciona, você precisa mudar np.where(np.isnan(a), a, 0)para np.where(~np.isnan(a), a, 0). Isso pode ser uma diferença nas versões usadas.
TehTris 01 de
1
@TehTris você está certo, obrigado. Eu mudei para o b = np.where(np.isnan(a), 0, a)que é mais simples do ~que eu acho.
Anton Protopopov
11

Um exemplo de código para a resposta de Drake usar nan_to_num:

>>> import numpy as np
>>> A = np.array([[1, 2, 3], [0, 3, np.NaN]])
>>> A = np.nan_to_num(A)
>>> A
array([[ 1.,  2.,  3.],
       [ 0.,  3.,  0.]])
serv-inc
fonte
3

Você pode usar numpy.nan_to_num :

numpy.nan_to_num (x): Substitua nan por zero e inf por números finitos .

Exemplo (ver doc):

>>> np.set_printoptions(precision=8)
>>> x = np.array([np.inf, -np.inf, np.nan, -128, 128])
>>> np.nan_to_num(x)
array([  1.79769313e+308,  -1.79769313e+308,   0.00000000e+000,
        -1.28000000e+002,   1.28000000e+002])
Bilal
fonte
1

nan nunca é igual a nan

if z!=z:z=0

então, para uma matriz 2D

for entry in nparr:
    if entry!=entry:entry=0
litepresença
fonte
Isso não funciona: entryé um array 1D, então o teste entry != entrynão fornece um booleano simples, mas aumenta ValueError.
Eric O Lebigot
-1

Você pode usar a função lambda, um exemplo para matriz 1D:

import numpy as np
a = [np.nan, 2, 3]
map(lambda v:0 if np.isnan(v) == True else v, a)

Isso lhe dará o resultado:

[0, 2, 3]
Mohanad Kaleia
fonte
-8

Para seus propósitos, se todos os itens forem armazenados como stre você apenas usar classificados como está usando e, em seguida, verifique o primeiro elemento e substitua-o por '0'

>>> l1 = ['88','NaN','67','89','81']
>>> n = sorted(l1,reverse=True)
['NaN', '89', '88', '81', '67']
>>> import math
>>> if math.isnan(float(n[0])):
...     n[0] = '0'
... 
>>> n
['0', '89', '88', '81', '67']
Senthil Kumaran
fonte
6
Seu comentário não é um pouco áspero? Eu sei o que é numpy, mas sabia que a matriz não será uma representação de string de números. Eu especificamente não considerei isso da perspectiva entorpecida, mas da perspectiva do python, se isso fosse útil.
Senthil Kumaran
2
Reordenar a matriz parece uma maneira confusa de resolver isso.
holografix
Preciso preservar a ordem do meu array. Não funcionará se você tiver vários 'NaN' em sua matriz.
3nrique0