Ignorer les valeurs aberrantes dans le boxplot ggplot2


132

Comment ignorer les valeurs aberrantes dans le boxplot ggplot2? Je ne veux pas simplement qu'ils disparaissent (c.-à-d. Outlier.size = 0), mais je veux qu'ils soient ignorés de telle sorte que l'axe des y est mis à l'échelle pour afficher le 1er / 3ème percentile. Mes valeurs aberrantes font que la "boîte" rétrécit si petit qu'elle est pratiquement une ligne. Existe-t-il des techniques pour gérer cela?

Modifier Voici un exemple:

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

entrez la description de l'image ici


Quelques exemples de données et un exemple reproductible vous permettront de vous aider plus facilement.
Andrie

3
mon fichier est de 200 méga! Prenez n'importe quel jeu de données contenant beaucoup de points de données entre le 1er et le 3e quantile et quelques valeurs aberrantes (vous n'en avez besoin que d'un). Si la valeur aberrante est éloignée du 1er / 3ème, les boîtes vont nécessairement se rétrécir pour s'adapter à la valeur aberrante
SFun28

Oui, c'est ce que j'avais en tête. Créez un tel jeu de données et utilisez dput () pour le publier ici avec l'instruction ggplot () que vous utilisez. Aidez nous à vous aider.
Andrie

Ne pouvez-vous pas simplement modifier les limites de l'axe y pour "zoomer" sur la partie de l'axe y qui vous intéresse?
Gavin Simpson

2
laissez-moi regarder ... Oh oui, désolé. fivenum()Faites simplement sur les données pour extraire ce qui, IIRC, est utilisé pour les charnières supérieures et inférieures des boxplots et utilisez cette sortie dans l' scale_y_continuous()appel que @Ritchie a montré. Cela peut être automatisé très facilement à l'aide des outils fournis par R et ggplot. Si vous devez également inclure les moustaches, envisagez d'utiliser boxplot.stats()pour obtenir les limites supérieure et inférieure des moustaches et utilisez-les ensuite scale_y_continuous().
Gavin Simpson

Réponses:


141

Voici une solution utilisant 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)

15
+1 pour le calcul automatique, +1 pour utiliser coord_cartesian pour zoomer plutôt que pour exclure les données
Ben Bolker

2
@Ben - vous avez deux comptes? =) @Ramnath - c'est une solution vraiment élégante
SFun28

7
En utilisant la méthode ci-dessus, les limites peuvent être biaisées par un petit extrême d'un côté et un grand extrême de l'autre, par exemple ylim <- c(-0.1, 1000) * 1.05donne [1] 0.105 1050. Pour obtenir des limites égales autour de la moyenne que vous pourriez utiliser ylim + c(-0.05, 0.05) * diff(ylim) / 2. Plus joli à mon avis.
Bram Visser

2
@Ramnath Que fait le $ stats [c (1,5)]?
lukeg

3
Le ne fonctionne pas si vous utilisez facet_grid(). Ensuite, vous avez des boxplots multibrins au lieu d'un. Ainsi, vous n'obtenez pas les bonnes limites.
WitheShadow

204

Permet geom_boxplot(outlier.shape = NA)de ne pas afficher les valeurs aberrantes et scale_y_continuous(limits = c(lower, upper))de modifier les limites de l'axe.

Un exemple.

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

En fait, comme Ramnath l'a montré dans sa réponse (et Andrie aussi dans les commentaires), il est plus logique de recadrer les échelles après avoir calculé la statistique, via coord_cartesian.

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

(Vous devrez probablement encore utiliser scale_y_continuouspour corriger les ruptures d'axe.)


1
Je devrais donc calculer le inférieur / supérieur - peut-être en calculant le 1er / 3ème centile? Cela signifie qu'il n'y a pas de moyen magique automatique de dire à gg-plot2 d'ignorer les valeurs aberrantes et de mettre à l'échelle intelligemment?
SFun28

38
Soyez prudent avec scale_y_continuous (limits = ...) Cela supprimera les données qui tombent en dehors des limites et effectuera ensuite les calculs statistiques. En d'autres termes, la moyenne et les autres résumés seront affectés. Si c'est ce que vous voulez, tant mieux. L'alternative est d'utiliser coord_cartesian (limits = ...) - cela «zoom» sans supprimer les données ou affecter les résumés.
Andrie

@Andrie - merci! Je ne veux pas que les résumés méchants et autres soient affectés.
SFun28

1
coord_cartesian()ne joue pas bien avec coord_flip(), d'après mon expérience, donc je préfère scale_y_continuous().
PatrickT

1
C'est la meilleure solution. La raison pour laquelle je veux masquer les valeurs aberrantes est que je trace également des points instables avec geom_jitter. Dans ce cas, les valeurs aberrantes ne font que gêner et donnent l'impression qu'il y a plus de points qu'il ne devrait y en avoir.
williamsurles

14

J'ai eu le même problème et j'ai précalculé les valeurs pour Q1, Q2, médiane, ymin, ymax en utilisant 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

Le résultat est un boxplot sans valeurs aberrantes. entrez la description de l'image ici


9

Une idée serait de winsorize les données dans une procédure en deux passes:

  1. exécuter une première passe, apprendre quelles sont les limites, par exemple une coupe à un centile donné, ou un écart-type N au-dessus de la moyenne, ou ...

  2. dans un deuxième passage, définissez les valeurs au-delà de la limite donnée à la valeur de cette limite

Je dois souligner qu'il s'agit d'une méthode désuète qui devrait être dominée par des techniques robustes plus modernes, mais vous la rencontrez toujours beaucoup.


1
Quiconque vient de voter en silence : laissez un commentaire pour expliquer pourquoi .
Dirk Eddelbuettel du

N'était-ce pas moi. Je voulais juste ajouter que le fait d'avoir des moustaches qui s'arrêtent aux centiles (généralement 10e et 90e) semble être très courant avec les données environnementales.
Richie Cotton

J'étais un +1 silencieux et j'aurais aimé en avoir un autre à offrir. La valorisation se fait presque toujours dans econ + finance. Si SFun a des valeurs aberrantes qui ruinent la visualisation des données, je me demande quel est leur effet sur l'analyse des données.
Richard Herron

J'ai relu ce post, vous avez mentionné que le windsorizing est une technique plus ancienne ... quelles seraient des techniques plus modernes?
SFun28

1
En général, des méthodes robustes comme un développement des 30 dernières années.
Dirk Eddelbuettel

2

L'option "coef" de la fonction geom_boxplot permet de changer le seuil de valeur aberrante en termes d'intervalle interquartile. Cette option est documentée pour la fonction stat_boxplot. Pour désactiver les valeurs aberrantes (en d'autres termes, elles sont traitées comme des données régulières), on peut au lieu d'utiliser la valeur par défaut de 1,5 spécifier une valeur de coupure très élevée:

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)

3
Cela ne fait qu'étendre les moustaches, il ne redimensionne pas du tout le graphique
Moody_Mudskipper

2

Si vous voulez forcer les moustaches à s'étendre aux valeurs max et min, vous pouvez modifier l' coefargument. La valeur par défaut pour coefest de 1,5 (c'est-à-dire que la longueur par défaut des moustaches est 1,5 fois l'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)

image de p0

image de p1


2

Ipaper :: geom_boxplot2 est exactement ce que vous voulez.

# 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)

entrez la description de l'image ici


Merci!! Testé avec mes données, fonctionne parfaitement! Je recommanderais cette solution, même si je ne suis pas sûr de la stabilité / du support à long terme des choses github.
Gildas
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.