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.


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)

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.


41

Que tal nan_to_num () ?


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

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

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

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

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]

-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']

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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.