Para ser claros, por "eliminar NaNs" te refieres a filtrar solo el subconjunto de valores no nulos . No "llenar los NaN con algún valor (cero, constante, media, mediana, etc.)"
smci
Respuestas:
362
Si está usando numpy para sus matrices, también puede usar
x = x[numpy.logical_not(numpy.isnan(x))]
Equivalentemente
x = x[~numpy.isnan(x)]
[Gracias a chbrown por la taquigrafía añadida]
Explicación
La función interna, numpy.isnandevuelve una matriz booleana / lógica que tiene el valor en Truetodas partes que xno es un número. Como queremos lo contrario, usamos el operador lógico-no, ~para obtener una matriz con Trues en todas partes que xsea un número válido.
Por último, usamos esta matriz lógica para indexar en la matriz original x, para recuperar solo los valores que no son NaN.
O x = x[~numpy.isnan(x)], que es equivalente a la respuesta original de mutzmatron, pero más corto. En caso de que quiera mantener sus infinitos alrededor, sepa eso numpy.isfinite(numpy.inf) == False, por supuesto, pero ~numpy.isnan(numpy.inf) == True.
chbrown
8
Para las personas que buscan resolver esto con un ndarray y mantener las dimensiones, use numpy donde :np.where(np.isfinite(x), x, 0)
BoltzmannBrain
1
TypeError: solo las matrices escalares enteras se pueden convertir a un índice escalar
remolque
1
@towry: esto está sucediendo porque su entrada, xno es una matriz numpy. Si desea utilizar la indexación lógica, debe ser una matriz, por ejemplox = np.array(x)
jmetz el
50
filter(lambda v: v==v, x)
funciona tanto para las listas como para la matriz numpy ya que v! = v solo para NaN
Un truco pero especialmente útil en el caso de que esté filtrando nans de una matriz de objetos con tipos mixtos, como cadenas y nans.
Austin Richardson
Solución muy limpia.
Moondra
2
Esto puede parecer inteligente, pero si oscurece la lógica y, en teoría, otros objetos (como las clases personalizadas) también pueden tener esta propiedad
Chris_Rands
También es útil porque solo necesita xespecificarse una vez en lugar de soluciones del tipo x[~numpy.isnan(x)]. Esto es conveniente cuando xse define mediante una expresión larga y no desea saturar el código creando una variable temporal para almacenar el resultado de esta expresión larga.
Christian O'Reilly
34
Prueba esto:
import mathprint[value for value in x ifnot math.isnan(value)]
Si está usando numpy, tanto mi respuesta como la de @ lazy1 son casi un orden de magnitud más rápidas que la comprensión de la lista: la solución de lazy1 es un poco más rápida (aunque técnicamente tampoco devolverá ningún valor infinito).
jmetz
No olvides los corchetes :)print ([value for value in x if not math.isnan(value)])
hypers
Si está usando numpy como la respuesta principal, puede usar esta respuesta de comprensión de la lista con el nppaquete: Entonces devuelve su lista sin las nans:[value for value in x if not np.isnan(value)]
yeliabsalohcin
23
Para mí, la respuesta de @jmetz no funcionó, sin embargo, el uso de pandas isnull () sí.
Descubrí que restablecer la misma variable (x) no eliminaba los valores reales de nan y tenía que usar una variable diferente. Establecerlo en una variable diferente eliminó los nans. p.ej
Esto es extraño; De acuerdo con los documentos , la indexación de matriz booleana (que es esto), está bajo indexación avanzada que aparentemente "siempre devuelve una copia de los datos", por lo que debería xsobrescribir con el nuevo valor (es decir, sin los NaNs ...) . ¿Puede proporcionar más información sobre por qué esto podría estar sucediendo?
jmetz
5
Como lo demuestran otros
x[~numpy.isnan(x)]
trabajos. Pero arrojará un error si el tipo de archivo numpy no es un tipo de datos nativo, por ejemplo, si es un objeto. En ese caso puedes usar pandas.
La respuesta aceptada cambia de forma para las matrices 2d. Presento una solución aquí, usando la funcionalidad Pandas dropna () . Funciona para matrices 1D y 2D. En el caso 2D, puede elegir el clima para soltar la fila o columna que contiene np.nan.
import pandas as pdimport numpy as npdef dropna(arr,*args,**kwarg):assert isinstance(arr, np.ndarray)
dropped=pd.DataFrame(arr).dropna(*args,**kwarg).valuesif arr.ndim==1:
dropped=dropped.flatten()return dropped
x = np.array([1400,1500,1600, np.nan, np.nan, np.nan ,1700])
y = np.array([[1400,1500,1600],[np.nan,0, np.nan],[1700,1800,np.nan]])print('='*20+' 1D Case: '+'='*20+'\nInput:\n',x,sep='')print('\ndropna:\n',dropna(x),sep='')print('\n\n'+'='*20+' 2D Case: '+'='*20+'\nInput:\n',y,sep='')print('\ndropna (rows):\n',dropna(y),sep='')print('\ndropna (columns):\n',dropna(y,axis=1),sep='')print('\n\n'+'='*20+' x[np.logical_not(np.isnan(x))] for 2D: '+'='*20+'\nInput:\n',y,sep='')print('\ndropna:\n',x[np.logical_not(np.isnan(x))],sep='')
Resultado:
====================1DCase:====================Input:[1400.1500.1600. nan nan nan 1700.]
dropna:[1400.1500.1600.1700.]====================2DCase:====================Input:[[1400.1500.1600.][ nan 0. nan][1700.1800. nan]]
dropna (rows):[[1400.1500.1600.]]
dropna (columns):[[1500.][0.][1800.]]==================== x[np.logical_not(np.isnan(x))]for2D:====================Input:[[1400.1500.1600.][ nan 0. nan][1700.1800. nan]]
dropna:[1400.1500.1600.1700.]
Bienvenido a SO! La solución que propone no responde al problema: su solución sustituye NaNs con un gran número, mientras que el OP solicitó eliminar por completo los elementos.
Pier Paolo
0
Este es mi enfoque para filtrar ndarray "X" para NaNs e infs,
Creo un mapa de filas sin ninguno NaNy ninguno de la infsiguiente manera:
La respuesta de @ jmetz es probablemente la que más necesita la gente; sin embargo, produce una matriz unidimensional, por ejemplo, hace que sea inutilizable eliminar filas o columnas enteras en matrices.
Para hacerlo, uno debe reducir la matriz lógica a una dimensión, luego indexar la matriz de destino. Por ejemplo, lo siguiente eliminará las filas que tengan al menos un valor NaN:
Respuestas:
Si está usando numpy para sus matrices, también puede usar
Equivalentemente
[Gracias a chbrown por la taquigrafía añadida]
Explicación
La función interna,
numpy.isnan
devuelve una matriz booleana / lógica que tiene el valor enTrue
todas partes quex
no es un número. Como queremos lo contrario, usamos el operador lógico-no,~
para obtener una matriz conTrue
s en todas partes quex
sea un número válido.Por último, usamos esta matriz lógica para indexar en la matriz original
x
, para recuperar solo los valores que no son NaN.fuente
x = x[numpy.isfinite(x)]
x = x[~numpy.isnan(x)]
, que es equivalente a la respuesta original de mutzmatron, pero más corto. En caso de que quiera mantener sus infinitos alrededor, sepa esonumpy.isfinite(numpy.inf) == False
, por supuesto, pero~numpy.isnan(numpy.inf) == True
.np.where(np.isfinite(x), x, 0)
x
no es una matriz numpy. Si desea utilizar la indexación lógica, debe ser una matriz, por ejemplox = np.array(x)
funciona tanto para las listas como para la matriz numpy ya que v! = v solo para NaN
fuente
x
especificarse una vez en lugar de soluciones del tipox[~numpy.isnan(x)]
. Esto es conveniente cuandox
se define mediante una expresión larga y no desea saturar el código creando una variable temporal para almacenar el resultado de esta expresión larga.Prueba esto:
Para más información, lea en Lista de comprensiones .
fuente
print ([value for value in x if not math.isnan(value)])
np
paquete: Entonces devuelve su lista sin las nans:[value for value in x if not np.isnan(value)]
Para mí, la respuesta de @jmetz no funcionó, sin embargo, el uso de pandas isnull () sí.
fuente
Haciendo lo anterior:
o
Descubrí que restablecer la misma variable (x) no eliminaba los valores reales de nan y tenía que usar una variable diferente. Establecerlo en una variable diferente eliminó los nans. p.ej
fuente
x
sobrescribir con el nuevo valor (es decir, sin los NaNs ...) . ¿Puede proporcionar más información sobre por qué esto podría estar sucediendo?Como lo demuestran otros
trabajos. Pero arrojará un error si el tipo de archivo numpy no es un tipo de datos nativo, por ejemplo, si es un objeto. En ese caso puedes usar pandas.
fuente
La respuesta aceptada cambia de forma para las matrices 2d. Presento una solución aquí, usando la funcionalidad Pandas dropna () . Funciona para matrices 1D y 2D. En el caso 2D, puede elegir el clima para soltar la fila o columna que contiene
np.nan
.Resultado:
fuente
Si estas usando
numpy
fuente
Una forma más simple es:
Documentación: https://docs.scipy.org/doc/numpy/reference/generated/numpy.nan_to_num.html
fuente
NaN
s con un gran número, mientras que el OP solicitó eliminar por completo los elementos.Este es mi enfoque para filtrar ndarray "X" para NaNs e infs,
Creo un mapa de filas sin ninguno
NaN
y ninguno de lainf
siguiente manera:idx es una tupla. Su segunda columna (
idx[1]
) contiene los índices de la matriz, donde no se encuentra NaN ni inf en la fila.Luego:
filtered_X
contiene X sinNaN
niinf
.fuente
La respuesta de @ jmetz es probablemente la que más necesita la gente; sin embargo, produce una matriz unidimensional, por ejemplo, hace que sea inutilizable eliminar filas o columnas enteras en matrices.
Para hacerlo, uno debe reducir la matriz lógica a una dimensión, luego indexar la matriz de destino. Por ejemplo, lo siguiente eliminará las filas que tengan al menos un valor NaN:
Ver más detalles aquí .
fuente