Erkennen und Filtern von Ausreißern

Das Filtern oder Transformieren von Ausreißern ist weitgehend eine Frage der Anwendung von Array-Operationen. Betrachtet einen DataFrame mit einigen normal verteilten Daten:

[1]:
import numpy as np
import pandas as pd


rng = np.random.default_rng()
df = pd.DataFrame(rng.normal(size=(1000, 4)))

df.describe()
[1]:
0 1 2 3
count 1000.000000 1000.000000 1000.000000 1000.000000
mean -0.010284 -0.018033 0.012603 -0.015950
std 1.006980 1.015495 0.989181 1.032210
min -3.175732 -3.720231 -3.093263 -2.889419
25% -0.647827 -0.683638 -0.644732 -0.747090
50% -0.030960 -0.011795 0.033418 -0.023026
75% 0.665872 0.677355 0.656409 0.692767
max 3.310321 3.484527 3.275656 3.527782

Angenommen, ihr wollt in einer der Spalten Werte finden, deren absoluter Wert größer als 3 oder kleiner als -3 ist:

[2]:
col = df[1]

col[col.abs() > 3]
[2]:
254   -3.238330
422    3.484527
464   -3.437452
476   -3.019482
499   -3.094016
621   -3.720231
674    3.145420
Name: 1, dtype: float64

Um alle Zeilen auszuwählen, in denen Wert größer 3 oder kleiner -3 in einer der Spalten ist, könnt ihr pandas.DataFrame.any auf einen booleschen DataFrame anwenden, wobei mit any(axis=1) üüberprüft wird, ob ein Wert in einer Zeile wahr ist:

[3]:
df[(df.abs() > 3).any(axis=1)]
[3]:
0 1 2 3
68 -0.913320 0.675847 -0.237511 3.070655
197 1.227823 -0.551239 3.275656 0.875736
254 0.562163 -3.238330 -0.808823 -0.130129
319 0.011201 0.110650 -1.336874 3.000621
370 0.998057 1.127185 -0.648043 3.117027
404 -0.340538 -2.698506 -3.093263 -0.399621
409 3.310321 1.442338 0.362357 -1.605350
422 0.175541 3.484527 0.432583 -1.932812
442 3.288727 1.135310 -0.368762 1.578203
464 1.496301 -3.437452 1.050452 0.070361
470 -0.187702 0.400744 3.081391 -0.937770
476 1.191677 -3.019482 -0.025482 1.082824
499 0.553608 -3.094016 -0.101979 0.225328
621 1.266543 -3.720231 -0.364275 1.231816
661 -1.055270 -0.486829 0.617043 3.527782
674 1.035528 3.145420 1.298255 1.106587
901 -3.175732 0.553589 -0.767643 0.718555
946 3.252568 -0.487513 -0.107456 1.845214

Auf dieser Grundlage können die Werte begrenzt werden auf ein Intervall zwischen -3 und 3. Hierfür verwenden wir die Anweisung np.sign(df), die Werte 1 und -1 erzeugt, je nachdem, ob die Werte in df positiv oder negativ sind:

[4]:
df[df.abs() > 3] = np.sign(df) * 3

df.describe()
[4]:
0 1 2 3
count 1000.000000 1000.000000 1000.000000 1000.000000
mean -0.010960 -0.017153 0.012340 -0.016666
std 1.003767 1.008652 0.987770 1.029968
min -3.000000 -3.000000 -3.000000 -2.889419
25% -0.647827 -0.683638 -0.644732 -0.747090
50% -0.030960 -0.011795 0.033418 -0.023026
75% 0.665872 0.677355 0.656409 0.692767
max 3.000000 3.000000 3.000000 3.000000