¿Cómo puedo eliminar a Nan de la lista Python / NumPy?

89

Tengo una lista que cuenta valores, uno de los valores que obtuve es 'nan'

countries= [nan, 'USA', 'UK', 'France']

Traté de eliminarlo, pero cada vez aparece un error

cleanedList = [x for x in countries if (math.isnan(x) == True)]
TypeError: a float is required

Cuando probé este:

cleanedList = cities[np.logical_not(np.isnan(countries))]
cleanedList = cities[~np.isnan(countries)]

TypeError: ufunc 'isnan' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe''
user3001937
fuente
4
Parece la cadena "nan", no un valor real de NaN.
BrenBarn
1
sí, es una cuerda. [x para x en países si x! = 'nan']
MarshalSHI
4
if condition == Truees innecesario, siempre puedes hacerlo if condition.
reem
Ninguna solución proporcionada hasta ahora no es satisfactoria. Tengo el mismo problema. Básicamente, no funciona con cadenas. Por tanto en su caso np.isnan('USA')le enviará el mismo mensaje de error. Si encuentro alguna solución, la subiré.
Yohan Obadia

Respuestas:

127

La pregunta ha cambiado, por lo que tiene la respuesta:

Las cadenas no se pueden probar usando math.isnanya que esto espera un argumento flotante. En su countrieslista, tiene flotadores y cuerdas.

En su caso, lo siguiente debería ser suficiente:

cleanedList = [x for x in countries if str(x) != 'nan']

Respuesta antigua

En su countrieslista, el literal 'nan'es una cadena, no el flotante de Python, nanque es equivalente a:

float('NaN')

En su caso, lo siguiente debería ser suficiente:

cleanedList = [x for x in countries if x != 'nan']
Comunidad
fuente
1
Lógicamente, lo que dices es cierto. Pero no funcionó conmigo.
user3001937
Entonces el problema está en otra área, la matriz que proporcionó son cadenas que math.isnanse corregirán naturalmente con los errores.
Si ! cuando imprimo la salida, obtengo esto: [nan, 'USA', 'UK', 'France']
user3001937
1
@ user3001937 He actualizado la respuesta según la nueva información
2
zhangxaochen: no es una cuerda, es un flotador. Mire cuidadosamente la respuesta actualizada; Lego Stormtroopr se está convirtiendo xen una cadena para que puedas compararlo. nansiempre devuelve falso para ==, incluso cuando se compara con nan, por lo que esa es la forma más fácil de compararlo.
Monica Cellio gratis
17

El problema proviene del hecho de que np.isnan()no maneja correctamente los valores de cadena. Por ejemplo, si lo hace:

np.isnan("A")
TypeError: ufunc 'isnan' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe''

Sin embargo, la versión de pandas pd.isnull()funciona para valores numéricos y de cadena:

pd.isnull("A")
> False

pd.isnull(3)
> False

pd.isnull(np.nan)
> True

pd.isnull(None)
> True
Yohan Obadia
fuente
14

Usando su ejemplo donde ...

countries= [nan, 'USA', 'UK', 'France']

Dado que nan no es igual a nan (nan! = Nan) y los países [0] = nan, debes observar lo siguiente:

countries[0] == countries[0]
False

Sin embargo,

countries[1] == countries[1]
True
countries[2] == countries[2]
True
countries[3] == countries[3]
True

Por lo tanto, lo siguiente debería funcionar:

cleanedList = [x for x in countries if x == x]
vlmercado
fuente
1
Esta es la única respuesta que funciona cuando tiene un flotador ('nan') en una lista de cadenas
kmundnic
12
import numpy as np

mylist = [3, 4, 5, np.nan]
l = [x for x in mylist if ~np.isnan(x)]

Esto debería eliminar todo el NaN. Por supuesto, supongo que no es una cadena aquí, sino un NaN ( np.nan) real .

Ajay Shah
fuente
1
Esto me da un error: TypeError: ufunc 'isnan' no es compatible con los tipos de entrada, y las entradas no se pudieron forzar de forma segura a ningún tipo compatible de acuerdo con la regla de conversión '' segura ''
Zak Keirn
1
¿Por qué no simplemente x[~ np.isnan(x)]:? No se necesita comprensión de listas en numpy. Por supuesto, supongo que x es una matriz numerosa.
bue
Supuse que x no va a ser una matriz numerosa como sugiere la pregunta.
Ajay Shah
Esperará flotación. No funcionará en listas con cadenas @ZakKeirn
Shirish Bajpai
5

use la indexación de lujo numpy :

In [29]: countries=np.asarray(countries)

In [30]: countries[countries!='nan']
Out[30]: 
array(['USA', 'UK', 'France'], 
      dtype='|S6')
zhangxaochen
fuente
5

si comprueba el tipo de elemento

type(countries[1])

el resultado será <class float> que puedas usar el siguiente código:

[i for i in countries if type(i) is not float]
Beyran11
fuente
4

Me gusta eliminar los valores faltantes de una lista como esta:

list_no_nan = [x for x in list_with_nan if pd.notnull(x)]
Aaron Inglaterra
fuente
1

En su ejemplo, 'nan'es una cadena, así que en lugar de usar isnan()solo verifique la cadena

Me gusta esto:

cleanedList = [x for x in countries if x != 'nan']
De serie
fuente
0

Otra forma de hacerlo incluiría usar un filtro como este:

countries = list(filter(lambda x: str(x) != 'nan', countries))
Sorin Dragan
fuente
-1

Noté que Pandas, por ejemplo, devolverá 'nan' para valores en blanco. Como no es una cadena, debe convertirla en una para que coincida. Por ejemplo:

ulist = df.column1.unique() #create a list from a column with Pandas which 
for loc in ulist:
    loc = str(loc)   #here 'nan' is converted to a string to compare with if
    if loc != 'nan':
        print(loc)
gorrión
fuente