Bevor wir die eigentliche Frage beantworten, sollten wir eine weitere stellen, die je nach Art Ihrer Daten sehr relevant ist:
Was ist ein Ausreißer?
Stellen Sie sich die Wertreihe [3, 2, 3, 4, 999]
vor (wobei die 999
scheinbar nicht hineinpasst) und analysieren Sie verschiedene Möglichkeiten der Ausreißererfassung
Z-Score
Das Problem hierbei ist, dass der betreffende Wert unsere Maße Mittelwert
und Standardabweichung
stark verfälscht, was zu unauffälligen z-Scores von ungefähr [-0.5, -0.5, -0.5, -0.5, 2.0]
führt, wobei jeder Wert innerhalb von zwei Standardabweichungen des Mittelwerts bleibt. Ein sehr großer Ausreißer kann daher Ihre gesamte Bewertung von Ausreißern verzerren. Ich würde von diesem Ansatz abraten.
Quantile-Filter
Ein wesentlich robusterer Ansatz wird in dieser Antwort beschrieben, indem die unteren und oberen 1% der Daten eliminiert werden. Dies eliminiert jedoch einen festen Anteil unabhängig davon, ob diese Daten wirklich Ausreißer sind. Sie könnten viele gültige Daten verlieren und andererseits immer noch einige Ausreißer behalten, wenn mehr als 1% oder 2% Ihrer Daten Ausreißer sind.
IQR-Abstand vom Median
Eine noch robusterer Version des Quantile-Prinzips: Eliminieren Sie alle Daten, die mehr als f
Mal die Interquartilsabstand vom Median der Daten entfernt sind. Das ist auch die Transformation, die beispielsweise von sklearn
's RobustScaler
verwendet wird. IQR und Median sind robust gegenüber Ausreißern, sodass Sie die Probleme des z-Wert-Ansatzes umgehen.
In einer Normalverteilung haben wir ungefähr iqr=1.35*s
, sodass Sie einen z=3
eines z-Wert-Filters in einen f=2.22
eines iqr-Filters übersetzen würden. Dies würde die 999
im obigen Beispiel ausschließen.
Die grundlegende Annahme ist, dass zumindest die "mittlere Hälfte" Ihrer Daten gültig ist und die Verteilung gut widerspiegelt, während Sie auch durcheinander kommen, wenn Ihre Verteilung breite Schwänze und ein schmales q_25%-bis-q_75%-Intervall hat.
Fortgeschrittene statistische Methoden
Natürlich gibt es ausgefeilte mathematische Methoden wie das Peirce-Kriterium, den Grubb's Test oder den Dixon's Q-Test, um nur einige zu nennen, die auch für nicht normalverteilte Daten geeignet sind. Keiner von ihnen ist leicht umsetzbar und wird daher nicht weiter behandelt.
Code
Austausch aller Ausreißer für alle numerischen Spalten durch np.nan
in einem Beispiel-Datenrahmen. Die Methode ist gegenüber allen von pandas bereitgestellten dtypes robust und kann problemlos auf Datenrahmen mit gemischten Typen angewendet werden:
import pandas as pd
import numpy as np
# Beispieldaten aller dtypes in pandas (Spalte 'a' hat einen Ausreißer) # dtype:
df = pd.DataFrame({'a': list(np.random.rand(8)) + [123456, np.nan], # float64
'b': [0,1,2,3,np.nan,5,6,np.nan,8,9], # int64
'c': [np.nan] + list("qwertzuio"), # object
'd': [pd.to_datetime(_) for _ in range(10)], # datetime64[ns]
'e': [pd.Timedelta(_) for _ in range(10)], # timedelta[ns]
'f': [True] * 5 + [False] * 5, # bool
'g': pd.Series(list("abcbabbcaa"), dtype="category")}) # category
cols = df.select_dtypes('number').columns # beschränkt auf a (float), b (int) und e (timedelta)
df_sub = df.loc[:, cols]
# OPTION 1: z-Wert-Filter: z-Wert < 3
lim = np.abs((df_sub - df_sub.mean()) / df_sub.std(ddof=0)) < 3
# OPTION 2: Quantile-Filter: Verwerfen der oberen und unteren 1% der Werte
lim = np.logical_and(df_sub < df_sub.quantile(0.99, numeric_only=False),
df_sub > df_sub.quantile(0.01, numeric_only=False))
# OPTION 3: iqr-Filter: innerhalb von 2,22 IQR (äquivalent zu z-Wert < 3)
iqr = df_sub.quantile(0.75, numeric_only=False) - df_sub.quantile(0.25, numeric_only=False)
lim = np.abs((df_sub - df_sub.median()) / iqr) < 2.22
# Ausreißer durch NaN ersetzen
df.loc[:, cols] = df_sub.where(lim, np.nan)
Um alle Zeilen zu löschen, die mindestens einen NaN-Wert enthalten:
df.dropna(subset=cols, inplace=True) # lösche Zeilen mit NaN in numerischen Spalten
# oder
df.dropna(inplace=True) # lösche Zeilen mit NaN in jeder Spalte
Verwendung von pandas 1.3 Funktionen: