Um klar zu sein, meinen Sie mit "NaNs entfernen", dass nur die Teilmenge der Nicht-Null-Werte herausgefiltert wird . Nicht "Füllen Sie die NaNs mit einem Wert (Null, Konstante, Mittelwert, Median usw.)"
smci
Antworten:
361
Wenn Sie numpy für Ihre Arrays verwenden, können Sie auch verwenden
x = x[numpy.logical_not(numpy.isnan(x))]
Gleichwertig
x = x[~numpy.isnan(x)]
[Danke an chbrown für die zusätzliche Abkürzung]
Erläuterung
Die innere Funktion numpy.isnangibt ein boolesches / logisches Array zurück, das Trueüberall den Wert hat, der xkeine Zahl ist. Da wir das Gegenteil wollen, verwenden wir den Operator logisch-nicht, ~um Trueüberall ein Array mit s zu erhalten, xdas eine gültige Zahl ist.
Zuletzt verwenden wir dieses logische Array, um in das ursprüngliche Array zu indizieren und xnur die Nicht-NaN-Werte abzurufen.
Oder x = x[~numpy.isnan(x)], was der ursprünglichen Antwort von Mutzmatron entspricht, aber kürzer ist. Wenn Sie Ihre Unendlichkeiten behalten möchten, wissen Sie das numpy.isfinite(numpy.inf) == Falsenatürlich, aber ~numpy.isnan(numpy.inf) == True.
Chbrown
8
Für Leute, die dies mit einem ndarray lösen und die Abmessungen beibehalten möchten, verwenden Sie numpy, wobei :np.where(np.isfinite(x), x, 0)
BoltzmannBrain
1
TypeError: Nur ganzzahlige skalare Arrays können in einen skalaren Index konvertiert werden
Towry
1
@towry: Dies geschieht, weil Ihre Eingabe xkein Numpy-Array ist. Wenn Sie die logische Indizierung verwendet werden soll, muss es ein Array sein - zum Beispielx = np.array(x)
jmetz
50
filter(lambda v: v==v, x)
funktioniert sowohl für Listen als auch für Numpy-Arrays, da v! = v nur für NaN ist
Ein Hack, der jedoch besonders nützlich ist, wenn Sie Nans aus einem Array von Objekten mit gemischten Typen wie Strings und Nans filtern.
Austin Richardson
Sehr saubere Lösung.
Moondra
2
Dies mag klug erscheinen, aber wenn die Logik verdeckt ist und theoretisch andere Objekte (wie benutzerdefinierte Klassen) ebenfalls diese Eigenschaft haben können
Chris_Rands
Auch nützlich, weil es xim Gegensatz zu Lösungen dieses Typs nur einmal angegeben werden muss x[~numpy.isnan(x)]. Dies ist praktisch, wenn dies xdurch einen langen Ausdruck definiert ist und Sie den Code nicht durch Erstellen einer temporären Variablen zum Speichern des Ergebnisses dieses langen Ausdrucks überladen möchten.
Christian O'Reilly
34
Versuche dies:
import mathprint[value for value in x ifnot math.isnan(value)]
Wenn Sie numpy verwenden, sind sowohl meine Antwort als auch die von @ lazy1 fast eine Größenordnung schneller als das Listenverständnis - die Lösung von lazy1 ist etwas schneller (obwohl technisch auch keine Unendlichkeitswerte zurückgegeben werden).
Jmetz
Vergessen Sie nicht die Klammern :)print ([value for value in x if not math.isnan(value)])
Hypers
Wenn Sie numpy wie die Top-Antwort verwenden, können Sie diese Antwort zum Listenverständnis mit dem npPaket verwenden: Geben Sie Ihre Liste also ohne die nans zurück:[value for value in x if not np.isnan(value)]
yeliabsalohcin
23
Für mich hat die Antwort von @jmetz nicht funktioniert, die Verwendung von pandas isnull () jedoch.
Ich fand heraus, dass das Zurücksetzen auf dieselbe Variable (x) die tatsächlichen Nanowerte nicht entfernte und eine andere Variable verwenden musste. Wenn Sie eine andere Variable festlegen, werden die Nans entfernt. z.B
Das ist merkwürdig; Laut den Dokumenten befindet sich die Boolesche Array-Indizierung (was dies ist) in der erweiterten Indizierung, die anscheinend "immer eine Kopie der Daten zurückgibt", daher sollten Sie xmit dem neuen Wert überschreiben (dh ohne die NaNs ...). . Können Sie weitere Informationen darüber geben, warum dies passieren könnte?
Jmetz
5
Wie von anderen gezeigt
x[~numpy.isnan(x)]
funktioniert. Es wird jedoch ein Fehler ausgegeben, wenn der numpy dtype kein nativer Datentyp ist, z. B. wenn es sich um ein Objekt handelt. In diesem Fall können Sie Pandas verwenden.
Die akzeptierte Antwort ändert ihre Form für 2D-Arrays. Ich präsentiere hier eine Lösung mit der Pandas dropna () -Funktionalität. Es funktioniert für 1D- und 2D-Arrays. Im 2D-Fall können Sie das Wetter auswählen, um die Zeile oder Spalte mit zu löschen 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='')
Ergebnis:
====================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.]
Willkommen bei SO! Die von Ihnen vorgeschlagene Lösung beantwortet das Problem nicht: Ihre Lösung ersetzt NaNs durch eine große Anzahl, während das OP darum bittet, die Elemente vollständig zu entfernen.
Pier Paolo
0
Dies ist mein Ansatz, um ndarray "X" nach NaNs und infs zu filtern.
Ich erstelle eine Karte von Zeilen ohne NaNund ohne infwie folgt:
@ jmetz 'Antwort ist wahrscheinlich die, die die meisten Leute brauchen; Es ergibt sich jedoch ein eindimensionales Array, das es beispielsweise unbrauchbar macht, ganze Zeilen oder Spalten in Matrizen zu entfernen.
Dazu sollte man das logische Array auf eine Dimension reduzieren und dann das Zielarray indizieren. Im Folgenden werden beispielsweise Zeilen entfernt, die mindestens einen NaN-Wert haben:
Antworten:
Wenn Sie numpy für Ihre Arrays verwenden, können Sie auch verwenden
Gleichwertig
[Danke an chbrown für die zusätzliche Abkürzung]
Erläuterung
Die innere Funktion
numpy.isnan
gibt ein boolesches / logisches Array zurück, dasTrue
überall den Wert hat, derx
keine Zahl ist. Da wir das Gegenteil wollen, verwenden wir den Operator logisch-nicht,~
umTrue
überall ein Array mit s zu erhalten,x
das eine gültige Zahl ist.Zuletzt verwenden wir dieses logische Array, um in das ursprüngliche Array zu indizieren und
x
nur die Nicht-NaN-Werte abzurufen.quelle
x = x[numpy.isfinite(x)]
x = x[~numpy.isnan(x)]
, was der ursprünglichen Antwort von Mutzmatron entspricht, aber kürzer ist. Wenn Sie Ihre Unendlichkeiten behalten möchten, wissen Sie dasnumpy.isfinite(numpy.inf) == False
natürlich, aber~numpy.isnan(numpy.inf) == True
.np.where(np.isfinite(x), x, 0)
x
kein Numpy-Array ist. Wenn Sie die logische Indizierung verwendet werden soll, muss es ein Array sein - zum Beispielx = np.array(x)
funktioniert sowohl für Listen als auch für Numpy-Arrays, da v! = v nur für NaN ist
quelle
x
im Gegensatz zu Lösungen dieses Typs nur einmal angegeben werden mussx[~numpy.isnan(x)]
. Dies ist praktisch, wenn diesx
durch einen langen Ausdruck definiert ist und Sie den Code nicht durch Erstellen einer temporären Variablen zum Speichern des Ergebnisses dieses langen Ausdrucks überladen möchten.Versuche dies:
Weitere Informationen finden Sie unter Listenverständnisse .
quelle
print ([value for value in x if not math.isnan(value)])
np
Paket verwenden: Geben Sie Ihre Liste also ohne die nans zurück:[value for value in x if not np.isnan(value)]
Für mich hat die Antwort von @jmetz nicht funktioniert, die Verwendung von pandas isnull () jedoch.
quelle
Gehen Sie wie folgt vor:
oder
Ich fand heraus, dass das Zurücksetzen auf dieselbe Variable (x) die tatsächlichen Nanowerte nicht entfernte und eine andere Variable verwenden musste. Wenn Sie eine andere Variable festlegen, werden die Nans entfernt. z.B
quelle
x
mit dem neuen Wert überschreiben (dh ohne die NaNs ...). . Können Sie weitere Informationen darüber geben, warum dies passieren könnte?Wie von anderen gezeigt
funktioniert. Es wird jedoch ein Fehler ausgegeben, wenn der numpy dtype kein nativer Datentyp ist, z. B. wenn es sich um ein Objekt handelt. In diesem Fall können Sie Pandas verwenden.
quelle
Die akzeptierte Antwort ändert ihre Form für 2D-Arrays. Ich präsentiere hier eine Lösung mit der Pandas dropna () -Funktionalität. Es funktioniert für 1D- und 2D-Arrays. Im 2D-Fall können Sie das Wetter auswählen, um die Zeile oder Spalte mit zu löschen
np.nan
.Ergebnis:
quelle
Wenn Sie verwenden
numpy
quelle
Ein einfachster Weg ist:
Dokumentation: https://docs.scipy.org/doc/numpy/reference/generated/numpy.nan_to_num.html
quelle
NaN
s durch eine große Anzahl, während das OP darum bittet, die Elemente vollständig zu entfernen.Dies ist mein Ansatz, um ndarray "X" nach NaNs und infs zu filtern.
Ich erstelle eine Karte von Zeilen ohne
NaN
und ohneinf
wie folgt:idx ist ein Tupel. Die zweite Spalte (
idx[1]
) enthält die Indizes des Arrays, in denen weder NaN noch inf in der Zeile gefunden wurden.Dann:
filtered_X
enthält X ohneNaN
nochinf
.quelle
@ jmetz 'Antwort ist wahrscheinlich die, die die meisten Leute brauchen; Es ergibt sich jedoch ein eindimensionales Array, das es beispielsweise unbrauchbar macht, ganze Zeilen oder Spalten in Matrizen zu entfernen.
Dazu sollte man das logische Array auf eine Dimension reduzieren und dann das Zielarray indizieren. Im Folgenden werden beispielsweise Zeilen entfernt, die mindestens einen NaN-Wert haben:
Weitere Details finden Sie hier .
quelle