convertir el valor nan a cero

95

Tengo una matriz de números 2D. Algunos de los valores de esta matriz son NaN. Quiero realizar ciertas operaciones usando esta matriz. Por ejemplo, considere la 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.]]

Estoy tratando de tomar cada fila, una a la vez, ordenarlas en orden inverso para obtener un máximo de 3 valores de la fila y tomar su promedio. El código que probé es:

# 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

Esto no funciona para filas que contienen NaN. Mi pregunta es, ¿existe una manera rápida de convertir todos los NaNvalores a cero en la matriz numérica 2D para que no tenga problemas con la clasificación y otras cosas que estoy tratando de hacer?

Curious2learn
fuente
1
each: map: return isNaN(value) ? 0 : value
kirilloid
@kirilloid: suena bien, ¿qué tal el uso de ejemplos?
serv-inc

Respuestas:

124

Esto debería funcionar:

from numpy import *

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

En el caso anterior where_are_NaNs es:

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

¿Dónde Aestá tu matriz 2D?

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

La función isnanproduce una matriz bool que indica dónde están los NaNvalores. Una matriz booleana se puede usar para indexar una matriz de la misma forma. Piense en ello como una máscara.

Paul
fuente
40

¿Qué tal nan_to_num () ?

Drake Guan
fuente
11
nan_to_num () también cambia infinitos; esto puede no ser deseado en algunos casos.
Agos
11
También es> 10 veces más lento que los otros métodos.
user48956
7
No estaba seguro acerca de la declaración "> 10x lento", así que lo comprobé. De hecho, es mucho más lento. Gracias por señalar esto.
Gabriel
16

Puede utilizar np.wherepara encontrar dónde tiene 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
fuente
1
tal como está, no funciona, necesita cambiar np.where(np.isnan(a), a, 0)a np.where(~np.isnan(a), a, 0). Sin embargo, esto podría ser una diferencia en las versiones utilizadas.
TehTris
1
@TehTris tienes razón, gracias. Lo cambié a lo b = np.where(np.isnan(a), 0, a)que es más sencillo que con ~lo que creo.
Anton Protopopov
10

Un ejemplo de código para usar la respuesta de Drakenan_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
fuente
3

Puede usar numpy.nan_to_num :

numpy.nan_to_num (x): Reemplaza nan con cero e inf con números finitos .

Ejemplo (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
fuente
1

nan nunca es igual a nan

if z!=z:z=0

así que para una matriz 2D

for entry in nparr:
    if entry!=entry:entry=0
presencia ligera
fuente
Esto no funciona: entryes una matriz 1D, por lo que la prueba entry != entryno da un booleano simple sino que aumenta ValueError.
Eric O Lebigot
-1

Puede usar la función lambda, un ejemplo de matriz 1D:

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

Esto le dará el resultado:

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

Para sus propósitos, si todos los elementos se almacenan como stry solo usa sorted como lo está usando y luego verifique el primer elemento y reemplácelo con '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
fuente
6
¿No es tu comentario un poco duro? Sé lo que es numpy, pero sabía que la matriz no será una representación de cadena de números. Específicamente, no le di una idea de esto desde una perspectiva numérica sino desde la perspectiva de Python, si eso fue útil.
Senthil Kumaran
2
Reordenar la matriz suena como una forma confusa de resolver esto.
holografix
Necesito preservar el orden de mi matriz. No funcionará si tiene varios 'NaN' en su matriz.
3nrique0