Come posso rimuovere Nan dall'elenco Python / NumPy


96

Ho una lista di valori di montagna, uno dei valori che ho ricevuto è 'nan'

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

Ho provato a rimuoverlo, ma ogni volta ricevo un errore

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

Quando ho provato questo:

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

4
Sembra la stringa "nan", non un valore NaN effettivo.
BrenBarn

1
sì, è una stringa. [x per x nei paesi se x! = 'nan']
MarshalSHI

4
if condition == Truenon è necessario, puoi sempre e basta if condition.
reem

Nessuna soluzione fornita finora non è soddisfacente. Ho lo stesso problema. Fondamentalmente, non funziona per le stringhe. Pertanto nel tuo caso np.isnan('USA')invierà lo stesso messaggio di errore. Se trovo una soluzione la caricherò.
Yohan Obadia

Risposte:


131

La domanda è cambiata, quindi ha la risposta:

Le stringhe non possono essere testate usando math.isnanpoiché questo richiede un argomento float. Nella tua countrieslista ci sono float e stringhe.

Nel tuo caso dovrebbe bastare quanto segue:

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

Vecchia risposta

Nella tua countrieslista, il letterale 'nan'è una stringa non il float Python nanche è equivalente a:

float('NaN')

Nel tuo caso dovrebbe bastare quanto segue:

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

1
Logicamente, quello che dici è vero. Ma non ha funzionato con me.
user3001937

Quindi il problema è in un'altra area, l'array che hai dato è stringhe che math.isnannaturalmente passeranno attraverso errori.

Sì ! quando stampo l'output, ho ottenuto questo: [nan, 'USA', 'UK', 'France']
user3001937

1
@ user3001937 Ho aggiornato la risposta in base alle nuove informazioni

2
zhangxaochen: non è una stringa, è un galleggiante. Guarda attentamente la risposta aggiornata; Lego Stormtroopr si sta convertendo xin una stringa in modo da poterlo confrontare. nanrestituisce sempre false per ==, anche se confrontato con nan, quindi questo è il modo più semplice per confrontarlo.
Monica Cellio gratuita il

17

Il problema deriva dal fatto che np.isnan()non gestisce correttamente i valori di stringa. Ad esempio, se:

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

Tuttavia la versione panda pd.isnull()funziona per valori numerici e stringa:

pd.isnull("A")
> False

pd.isnull(3)
> False

pd.isnull(np.nan)
> True

pd.isnull(None)
> True

15

Usando il tuo esempio dove ...

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

Poiché nan non è uguale a nan (nan! = Nan) e countries [0] = nan, dovresti osservare quanto segue:

countries[0] == countries[0]
False

Però,

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

Pertanto, dovrebbe funzionare quanto segue:

cleanedList = [x for x in countries if x == x]

1
Questa è l'unica risposta che funziona quando hai un float ('nan') in un elenco di stringhe
kmundnic

13
import numpy as np

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

Questo dovrebbe rimuovere tutto NaN. Ovviamente, presumo che qui non sia una stringa, ma l'effettivo NaN ( np.nan).


1
Questo mi dà un errore: TypeError: ufunc 'isnan' non supportato per i tipi di input e gli input non possono essere forzati in modo sicuro a nessun tipo supportato secondo la regola di casting '' safe ''
Zak Keirn

1
Perché non semplicemente x[~ np.isnan(x)]:? Nessuna comprensione della lista necessaria in numpy. Ovviamente, presumo che x sia un array numpy.
bue

Ho pensato che x non sarebbe stato un array numpy come suggerito dalla domanda.
Ajay Shah

Aspetterà il galleggiante. Non funzionerà su elenchi con stringhe @ZakKeirn
Shirish Bajpai

7

Mi piace rimuovere i valori mancanti da un elenco come questo:

list_no_nan = [x for x in list_with_nan if pd.notnull(x)]

6

se controlli il tipo di elemento

type(countries[1])

il risultato sarà <class float> così puoi usare il seguente codice:

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


2

Un altro modo per farlo includerebbe l'uso di filtri come questo:

countries = list(filter(lambda x: str(x) != 'nan', countries))

1

Nel tuo esempio 'nan'è una stringa, quindi invece di usare isnan()controlla la stringa

come questo:

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

-1

Ho notato che Panda, ad esempio, restituirà "nan" per valori vuoti. Poiché non è una stringa, è necessario convertirla in una per farla corrispondere. Per esempio:

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)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.