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 |