Wie kann ich Nan aus der Liste Python / NumPy entfernen?

89

Ich habe eine Liste mit Countain-Werten. Einer der Werte, die ich erhalten habe, ist 'nan'.

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

Ich habe versucht, es zu entfernen, aber ich erhalte jedes Mal eine Fehlermeldung

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

Als ich es versuchte:

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
quelle
4
Das sieht aus wie die Zeichenfolge "nan", kein tatsächlicher NaN-Wert.
BrenBarn
1
Ja, es ist eine Zeichenfolge. [x für x in Ländern, wenn x! = 'nan']
MarshalSHI
4
if condition == Trueist unnötig, kann man immer einfach machen if condition.
Reem
Bisher ist keine Lösung nicht zufriedenstellend. Ich habe das gleiche Problem. Grundsätzlich funktioniert es nicht für Strings. Daher wird in Ihrem Fall np.isnan('USA')die gleiche Fehlermeldung gesendet. Wenn ich eine Lösung finde, werde ich sie hochladen.
Yohan Obadia

Antworten:

127

Die Frage hat sich geändert, ebenso die Antwort:

Strings können nicht mit getestet werden, math.isnanda dies ein float-Argument erwartet. In Ihrer countriesListe haben Sie Floats und Strings.

In Ihrem Fall sollte Folgendes ausreichen:

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

Alte Antwort

In Ihrer countriesListe ist das Literal 'nan'eine Zeichenfolge, nicht das Python-Float. Dies nanentspricht:

float('NaN')

In Ihrem Fall sollte Folgendes ausreichen:

cleanedList = [x for x in countries if x != 'nan']
Gemeinschaft
quelle
1
Logischerweise ist das, was Sie sagen, wahr. Aber bei mir hat es nicht geklappt.
user3001937
Dann liegt das Problem in einem anderen Bereich. Das Array, das Sie angegeben haben, sind Zeichenfolgen, mit denen math.isnannatürlich Fehler auftreten.
Ja ! Als ich die Ausgabe druckte, bekam ich
Folgendes
1
@ user3001937 Ich habe die Antwort basierend auf den neuen Informationen aktualisiert
2
zhangxaochen: es ist kein string, es ist ein float. Schauen Sie sich die aktualisierte Antwort genau an. Lego Stormtroopr konvertiert xin einen String, damit Sie ihn vergleichen können. nanGibt immer false für zurück ==, auch im Vergleich zu nan. Dies ist der einfachste Weg, dies zu vergleichen.
Kostenlose Monica Cellio
17

Das Problem ergibt sich aus der Tatsache, dass np.isnan()Zeichenfolgenwerte nicht korrekt behandelt werden. Wenn Sie zum Beispiel Folgendes tun:

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

Die Pandas-Version pd.isnull()funktioniert jedoch für numerische Werte und Zeichenfolgenwerte:

pd.isnull("A")
> False

pd.isnull(3)
> False

pd.isnull(np.nan)
> True

pd.isnull(None)
> True
Yohan Obadia
quelle
13

Verwenden Sie Ihr Beispiel, wo ...

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

Da nan nicht gleich nan (nan! = Nan) und Ländern [0] = nan ist, sollten Sie Folgendes beachten:

countries[0] == countries[0]
False

Jedoch,

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

Daher sollte Folgendes funktionieren:

cleanedList = [x for x in countries if x == x]
vlmercado
quelle
1
Dies ist die einzige Antwort, die funktioniert, wenn Sie einen Float ('nan') in einer Liste von Strings haben
kmundnic
12
import numpy as np

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

Dies sollte alles NaN entfernen. Natürlich gehe ich davon aus, dass es sich hier nicht um einen String handelt, sondern um tatsächliches NaN ( np.nan).

Ajay Shah
quelle
1
Dies gibt mir einen Fehler: TypeError: ufunc 'isnan' wird für die Eingabetypen nicht unterstützt, und die Eingaben konnten gemäß der Casting-Regel '' safe '' nicht sicher zu unterstützten Typen gezwungen werden
Zak Keirn
1
Warum nicht einfach : x[~ np.isnan(x)]? In numpy ist kein Listenverständnis erforderlich. Natürlich gehe ich davon aus, dass x ein Numpy-Array ist.
bue
Ich nahm an, dass x kein Numpy-Array sein wird, wie die Frage vorschlug.
Ajay Shah
Es wird Float erwarten. Arbeitet nicht an Listen mit Strings @ZakKeirn
Shirish Bajpai
5

Verwenden Sie numpy Fancy Indexing :

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

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

wenn Sie nach dem Elementtyp suchen

type(countries[1])

Das Ergebnis ist, <class float> dass Sie den folgenden Code verwenden können:

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

Ich möchte fehlende Werte aus einer Liste wie dieser entfernen:

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

In Ihrem Beispiel 'nan'ist eine Zeichenkette , so dass anstelle der Verwendung isnan()nur für die Zeichenfolge überprüfen

so was:

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

Eine andere Möglichkeit wäre die Verwendung eines Filters wie folgt:

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

Mir ist aufgefallen, dass Pandas zum Beispiel für leere Werte 'nan' zurückgeben. Da es sich nicht um eine Zeichenfolge handelt, müssen Sie sie in eine konvertieren, um sie abzugleichen. Zum Beispiel:

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)
Spatz
quelle