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?


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)

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.


40

¿Qué tal nan_to_num () ?


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

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


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

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

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]

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

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
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.