Ignorieren Sie Ausreißer im Boxplot von ggplot2

132

Wie würde ich Ausreißer im ggplot2-Boxplot ignorieren? Ich möchte nicht einfach, dass sie verschwinden (dh outlier.size = 0), aber ich möchte, dass sie so ignoriert werden, dass die y-Achse so skaliert wird, dass das 1./3. Perzentil angezeigt wird. Meine Ausreißer bewirken, dass die "Box" so klein wird, dass sie praktisch eine Linie ist. Gibt es einige Techniken, um damit umzugehen?

Bearbeiten Hier ist ein Beispiel:

y = c(.01, .02, .03, .04, .05, .06, .07, .08, .09, .5, -.6)
qplot(1, y, geom="boxplot")

Geben Sie hier die Bildbeschreibung ein

SFun28
quelle
Einige Beispieldaten und ein reproduzierbares Beispiel erleichtern die Unterstützung.
Andrie
3
meine datei ist 200 meg! Nehmen Sie einfach einen Datensatz, in dem sich zwischen dem 1. und 3. Quantil viele Datenpunkte und einige Ausreißer befinden (Sie benötigen nur 1). Wenn der Ausreißer weit vom
1./3. Entfernt ist, werden
Ja, das hatte ich mir vorgestellt. Erstellen Sie ein solches Dataset und veröffentlichen Sie es mit dput () hier zusammen mit der von Ihnen verwendeten Anweisung ggplot (). Helfen Sie uns, Ihnen zu helfen.
Andrie
Können Sie nicht einfach die Grenzen der y-Achse ändern, um den Teil der y-Achse, an dem Sie interessiert sind, zu "zoomen"?
Gavin Simpson
2
lass mich schauen .... Oh ja, sorry. fivenum()Verwenden Sie einfach die Daten, um zu extrahieren, was IIRC für die oberen und unteren Scharniere von Boxplots verwendet wird, und verwenden Sie diese Ausgabe in dem scale_y_continuous()Aufruf, den @Ritchie angezeigt hat. Dies kann mit den Tools R und ggplot sehr einfach automatisiert werden. Wenn Sie auch die Whisker einbeziehen müssen, ziehen Sie die Verwendung boxplot.stats()in Betracht , um die oberen und unteren Grenzwerte für die Whisker zu ermitteln, und verwenden Sie dann in scale_y_continuous().
Gavin Simpson

Antworten:

140

Hier ist eine Lösung mit boxplot.stats

# create a dummy data frame with outliers
df = data.frame(y = c(-100, rnorm(100), 100))

# create boxplot that includes outliers
p0 = ggplot(df, aes(y = y)) + geom_boxplot(aes(x = factor(1)))


# compute lower and upper whiskers
ylim1 = boxplot.stats(df$y)$stats[c(1, 5)]

# scale y limits based on ylim1
p1 = p0 + coord_cartesian(ylim = ylim1*1.05)
Ramnath
quelle
15
+1 für die automatische Berechnung, +1 für die Verwendung von coord_cartesian zum Zoomen, anstatt Daten auszuschließen
Ben Bolker
2
@ Ben - hast du zwei Accounts? =) @ Ramnath - das ist eine wirklich elegante Lösung
SFun28
7
Unter Verwendung der obigen Verfahren, Grenzen könnte durch eine kleine extreme auf der einen Seite vorbelastet bekommen und und große extreme auf der anderen, zum Beispiel ylim <- c(-0.1, 1000) * 1.05gibt [1] 0.105 1050. Um gleiche Grenzen um den Mittelwert zu erhalten, den Sie verwenden könnten ylim + c(-0.05, 0.05) * diff(ylim) / 2. Meiner Meinung nach schöner.
Bram Visser
2
@Ramnath was machen die $ stats [c (1,5)]?
Lukeg
3
Das funktioniert nicht, wenn Sie verwenden facet_grid(). Dann haben Sie mehrere Boxplots anstelle von einem. Somit bekommen Sie nicht die richtigen Grenzen.
WitheShadow
204

Verwenden Sie geom_boxplot(outlier.shape = NA)diese Option , um die Ausreißer nicht anzuzeigen und die Achsengrenzen scale_y_continuous(limits = c(lower, upper))zu ändern.

Ein Beispiel.

n <- 1e4L
dfr <- data.frame(
  y = exp(rlnorm(n)),  #really right-skewed variable
  f = gl(2, n / 2)
)

p <- ggplot(dfr, aes(f, y)) + 
  geom_boxplot()
p   # big outlier causes quartiles to look too slim

p2 <- ggplot(dfr, aes(f, y)) + 
  geom_boxplot(outlier.shape = NA) +
  scale_y_continuous(limits = quantile(dfr$y, c(0.1, 0.9)))
p2  # no outliers plotted, range shifted

Wie Ramnath in seiner Antwort (und auch Andrie in den Kommentaren) gezeigt hat, ist es tatsächlich sinnvoller, die Skalen nach der Berechnung der Statistik über zuzuschneiden coord_cartesian.

coord_cartesian(ylim = quantile(dfr$y, c(0.1, 0.9)))

(Sie müssen wahrscheinlich noch verwenden scale_y_continuous, um die Achsenbrüche zu beheben.)

Richie Cotton
quelle
1
Also müsste ich das untere / obere berechnen - vielleicht durch Berechnen des 1./3. Perzentils? Das heißt, es gibt keine automatische Möglichkeit, gg-plot2 anzuweisen, Ausreißer zu ignorieren und intelligent zu skalieren?
SFun28
38
Seien Sie vorsichtig mit scale_y_continuous (Grenzen = ...). Dadurch werden Daten entfernt, die außerhalb der Grenzen liegen, und anschließend werden die statistischen Berechnungen durchgeführt. Mit anderen Worten, der Mittelwert und andere Zusammenfassungen werden beeinflusst. Wenn es das ist, was du willst, dann großartig. Die Alternative ist die Verwendung von coord_cartesian (limit = ...) - dies vergrößert das Bild, ohne Daten zu entfernen oder die Zusammenfassungen zu beeinflussen.
Andrie
@Andrie - danke! Ich möchte nicht, dass meine und andere Zusammenfassungen betroffen sind.
SFun28
1
coord_cartesian()spielt coord_flip()meiner erfahrung nach nicht gut damit , also bevorzuge ich scale_y_continuous().
PatrickT
1
Dies ist die beste Lösung. Der Grund, warum ich Ausreißer ausblenden möchte, ist, dass ich mit geom_jitter auch verwackelte Punkte zeichne. In diesem Fall stören die Ausreißer nur und lassen es so aussehen, als gäbe es mehr Punkte als es sein sollte.
Williamsurles
14

Ich hatte das gleiche Problem und berechnete die Werte für Q1, Q2, Median, ymin, ymax mit boxplot.stats:

# Load package and generate data
library(ggplot2)
data <- rnorm(100)

# Compute boxplot statistics
stats <- boxplot.stats(data)$stats
df <- data.frame(x="label1", ymin=stats[1], lower=stats[2], middle=stats[3], 
                 upper=stats[4], ymax=stats[5])

# Create plot
p <- ggplot(df, aes(x=x, lower=lower, upper=upper, middle=middle, ymin=ymin, 
                    ymax=ymax)) + 
    geom_boxplot(stat="identity")
p

Das Ergebnis ist ein Boxplot ohne Ausreißer. Geben Sie hier die Bildbeschreibung ein

Matthias Munz
quelle
9

Eine Idee wäre, winsorize die Daten in einem Zwei-Pass - Verfahren:

  1. Führen Sie einen ersten Durchgang durch, lernen Sie die Grenzen kennen, z. B. einen Schnitt bei einem bestimmten Perzentil oder eine N-Standardabweichung über dem Mittelwert oder ...

  2. Setzen Sie in einem zweiten Durchgang die Werte jenseits der angegebenen Grenze auf den Wert dieser Grenze

Ich sollte betonen, dass dies eine altmodische Methode ist, die von moderneren robusten Techniken dominiert werden sollte, aber Sie stoßen immer noch häufig darauf.

Dirk Eddelbuettel
quelle
1
Wer gerade still gestimmt hat : Hinterlasse einen Kommentar, um das Warum zu erklären .
Dirk Eddelbuettel
War ich nicht. Ich wollte nur hinzufügen, dass Whisker, die bei Perzentilen (normalerweise 10. und 90.) anhalten, bei Umweltdaten sehr häufig vorkommen.
Richie Cotton
Ich war ein stiller +1 und wünschte, ich hätte einen anderen zu bieten. Winsorizing wird fast immer in der Wirtschaft + Finanzen durchgeführt. Wenn SFun Ausreißer hat, die die Datenvisualisierung ruinieren, frage ich mich, wie sie sich auf die Datenanalyse auswirken.
Richard Herron
Als Sie diesen Beitrag noch einmal gelesen haben, haben Sie erwähnt, dass Windsurfen eine ältere Technik ist. Was wären modernere Techniken?
SFun28
1
Im Allgemeinen robuste Methoden als Entwicklung der letzten 30+ Jahre.
Dirk Eddelbuettel
2

Mit der Option "coef" der Funktion geom_boxplot kann der Ausreißer-Cutoff in Bezug auf Interquartilbereiche geändert werden. Diese Option ist für die Funktion stat_boxplot dokumentiert. Um Ausreißer zu deaktivieren (mit anderen Worten, sie werden als reguläre Daten behandelt), kann anstelle des Standardwerts von 1,5 ein sehr hoher Grenzwert angegeben werden:

library(ggplot2)
# generate data with outliers:
df = data.frame(x=1, y = c(-10, rnorm(100), 10)) 
# generate plot with increased cutoff for outliers:
ggplot(df, aes(x, y)) + geom_boxplot(coef=1e30)
eckart
quelle
3
Es verlängert nur die Schnurrhaare, es skaliert das Diagramm überhaupt nicht neu
Moody_Mudskipper
2

Wenn Sie die Whisker zwingen möchten, sich auf die Max- und Min-Werte auszudehnen, können Sie das coefArgument optimieren . Der Standardwert für coefist 1,5 (dh die Standardlänge der Whisker beträgt das 1,5-fache des IQR).

# Load package and create a dummy data frame with outliers 
#(using example from Ramnath's answer above)
library(ggplot2)
df = data.frame(y = c(-100, rnorm(100), 100))

# create boxplot that includes outliers
p0 = ggplot(df, aes(y = y)) + geom_boxplot(aes(x = factor(1)))

# create boxplot where whiskers extend to max and min values
p1 = ggplot(df, aes(y = y)) + geom_boxplot(aes(x = factor(1)), coef = 500)

Bild von p0

Bild von p1

IggyM
quelle
2

Ipaper :: geom_boxplot2 ist genau das, was Sie wollen.

# devtools::install_github('kongdd/Ipaper')
library(Ipaper)
library(ggplot2)
p <- ggplot(mpg, aes(class, hwy))
p + geom_boxplot2(width = 0.8, width.errorbar = 0.5)

Geben Sie hier die Bildbeschreibung ein

Dongdong Kong
quelle
Vielen Dank!! Getestet mit meinen Daten, funktioniert einwandfrei! Ich würde diese Lösung empfehlen, obwohl ich mir über die Stabilität / Langzeitunterstützung von Github-Dingen nicht sicher bin.
Gildas