Comment supprimer les valeurs aberrantes d'un ensemble de données

98

J'ai des données multivariées sur la beauté par rapport aux âges. Les âges varient de 20 à 40 ans à des intervalles de 2 (20, 22, 24 ... 40), et pour chaque enregistrement de données, ils reçoivent un âge et une cote de beauté de 1 à 5. Lorsque je fais des boîtes à moustaches de ces données (âges sur l'axe X, cotes de beauté sur l'axe Y), il y a des valeurs aberrantes tracées en dehors des moustaches de chaque boîte.

Je souhaite supprimer ces valeurs aberrantes de la trame de données elle-même, mais je ne sais pas comment R calcule les valeurs aberrantes pour ses boîtes à moustaches. Voici un exemple de ce à quoi mes données pourraient ressembler. entrez la description de l'image ici

Dan Q
la source
2
La boxplotfonction renvoie les valeurs aberrantes (parmi d'autres statistiques) de manière invisible. Essayez de foo <- boxplot(...); foolire ?boxplotpour comprendre la sortie.
Joshua Ulrich
Vous devriez modifier votre question en fonction du commentaire que vous avez donné sur la réponse de @ Prasad!
aL3xa
@ aL3xa: c'est dans la première phrase du deuxième paragraphe.
Joshua Ulrich
24
Pertinentes: davidmlane.com/ben/outlier.gif
eyjo
Pouvez-vous envoyer un lien vers les données?
wordsforthewise

Réponses:

120

OK, vous devriez appliquer quelque chose comme ça à votre ensemble de données. Ne remplacez pas et enregistrez ou vous détruirez vos données! Et, au fait, vous ne devriez (presque) jamais supprimer les valeurs aberrantes de vos données:

remove_outliers <- function(x, na.rm = TRUE, ...) {
  qnt <- quantile(x, probs=c(.25, .75), na.rm = na.rm, ...)
  H <- 1.5 * IQR(x, na.rm = na.rm)
  y <- x
  y[x < (qnt[1] - H)] <- NA
  y[x > (qnt[2] + H)] <- NA
  y
}

Pour le voir en action:

set.seed(1)
x <- rnorm(100)
x <- c(-10, x, 10)
y <- remove_outliers(x)
## png()
par(mfrow = c(1, 2))
boxplot(x)
boxplot(y)
## dev.off()

Et encore une fois, vous ne devriez jamais faire cela par vous-même, les valeurs aberrantes sont juste censées être! =)

EDIT: j'ai ajouté na.rm = TRUEpar défaut.

EDIT2:quantile fonction supprimée , indice ajouté, donc rendu la fonction plus rapide! =)

entrez la description de l'image ici

aL3xa
la source
Merci pour l'aide! Je pense que si R est capable de produire les valeurs aberrantes dans boxplot, je ne devrais pas avoir à faire ces calculs intermédiaires. Quant à la suppression des valeurs aberrantes, c'est juste pour une affectation.
Dan Q
3
OK, il me manque quelque chose ici. Vous souhaitez supprimer les valeurs aberrantes des données afin de pouvoir les tracer avec boxplot. C'est gérable, et vous devriez alors marquer la réponse de @ Prasad, puisque vous avez répondu à votre question. Si vous souhaitez exclure les valeurs aberrantes à l'aide de la "règle des valeurs aberrantes" q +/- (1.5 * H), exécutez donc une analyse, puis utilisez cette fonction. BTW, je l'ai fait à partir de zéro, sans googler, donc il y a une chance que j'ai réinventé la roue avec cette fonction de la mienne ...
aL3xa
10
Vous ne devriez pas poser de questions sur les devoirs sur stackoverflow!
hadley
7
Cela veut-il dire que nous ne devrions pas non plus y répondre? =)
aL3xa
5
"les valeurs aberrantes sont simplement censées être"? Pas nécessairement. Ils peuvent provenir d'erreurs de mesure et doivent être soigneusement examinés. Lorsque la valeur aberrante est trop grande, cela peut signifier quelque chose, ou pas tellement. C'est pourquoi (du moins en biologie) la médiane en dit généralement plus sur une population que la moyenne.
Rodrigo
133

Personne n'a publié la réponse la plus simple:

x[!x %in% boxplot.stats(x)$out]

Voir aussi ceci: http://www.r-statistics.com/2011/01/how-to-label-all-the-outliers-in-a-boxplot/

J. Win.
la source
4
Vraiment élégant. Merci. Mais il faut être prudent si la distribution a plus d'un mode et que les valeurs aberrantes ne sont en fait que peu nombreuses et dispersées.
KarthikS
Cela aurait été formidable si vous pouviez en obtenir l'index dans un ensemble de données. La façon dont vous avez terminé filtrera en fonction de la valeur des données. Si la boîte à moustaches fait également du regroupement, la même valeur de données ne sera pas nécessairement aberrante dans chaque groupe
adam
2
Il est également important de mentionner que cela ne modifie pas l'ensemble de données. Ceci est juste une méthode de filtrage. Donc, si vous avez l'intention d'utiliser l'ensemble de données sans valeurs aberrantes, attribuez-le à une variable. par exempleresult = x[!x %in% boxplot.stats(x)$out]
Victor Augusto
Avoir une seule ligne de code ne signifie pas nécessairement que c'est simple! Il n'est pas toujours facile de comprendre un code sur une ligne, spécialement pour les débutants, et sans commentaires.
PeyM87
29

À utiliser outline = FALSEcomme option lorsque vous faites la boîte à moustaches (lisez l'aide!).

> m <- c(rnorm(10),5,10)
> bp <- boxplot(m, outline = FALSE)

entrez la description de l'image ici

Prasad Chalasani
la source
4
en effet, cela supprimera les valeurs aberrantes du boxplot lui-même, mais je veux supprimer les valeurs aberrantes de la trame de données.
Dan Q
2
Je vois, alors comme @Joshua l'a dit, vous devez regarder les données renvoyées par la fonction boxplot (en particulier les éléments outet groupdans la liste).
Prasad Chalasani
16

La fonction boxplot renvoie les valeurs utilisées pour faire le tracé (ce qui est en fait ensuite fait par bxp ():

bstats <- boxplot(count ~ spray, data = InsectSprays, col = "lightgray") 
#need to "waste" this plot
bstats$out <- NULL
bstats$group <- NULL
bxp(bstats)  # this will plot without any outlier points

Je n'ai pas répondu à la question précise à dessein parce que je considère qu'il s'agit d'une erreur statistique de supprimer les «valeurs aberrantes». Je considère qu'il est acceptable de ne pas les tracer dans une boîte à moustaches, mais les supprimer simplement parce qu'ils dépassent un certain nombre d'écarts types ou un certain nombre de largeurs inter-quartiles est une modification systématique et non scientifique du dossier d'observation.

IRTFM
la source
4
Eh bien, contourner la question sans savoir pourquoi la question a été posée n'est pas non plus une bonne pratique. Oui, il n'est pas bon de supprimer les «valeurs aberrantes» des données, mais vous avez parfois besoin des données sans valeurs aberrantes pour des tâches spécifiques. Dans une mission de statistiques que j'ai eue récemment, nous avons dû visualiser un ensemble sans ses valeurs aberrantes pour déterminer le meilleur modèle de régression à utiliser pour les données. Donc là!
Alex Essilfie
4
Je ne considère pas les conseils que vous avez peut-être reçus à cet égard de «déterminer le meilleur modèle de régression» pour être particulièrement convaincant. Au lieu de cela, si vous deviez supprimer des valeurs aberrantes dans ce but vaguement énoncé, je pense que cela reflète mal les personnes qui l'ont conseillé plutôt que de prouver l'invalidité de ma position.
IRTFM
Je suppose que c'est légitime quand vous savez que vous supprimez le "bruit". en particulier dans les données physiologiques.
roscoe1895
Oui. Si vous avez de bonnes raisons de croire qu'un processus distinct crée le signal, cela justifie la suppression des données.
IRTFM
9

J'ai recherché des packages liés à la suppression des valeurs aberrantes, et j'ai trouvé ce package (appelé étonnamment "outliers"!): Https://cran.r-project.org/web/packages/outliers/outliers.pdf
si vous le parcourez vous voir différentes façons de supprimer les valeurs aberrantes et parmi elles, j'ai trouvé celle qui est la rm.outlierplus pratique à utiliser et comme indiqué dans le lien ci-dessus: "Si la valeur aberrante est détectée et confirmée par des tests statistiques, cette fonction peut la supprimer ou la remplacer par la moyenne ou la médiane de l'échantillon" et voici également la partie utilisation de la même source:
" Utilisation

rm.outlier(x, fill = FALSE, median = FALSE, opposite = FALSE)

Arguments
x un ensemble de données, le plus souvent un vecteur. Si l'argument est une trame de données, la valeur aberrante est supprimée de chaque colonne par sapply. Le même comportement est appliqué par apply lorsque la matrice est donnée.
fill Si la valeur est TRUE, la médiane ou la moyenne est placée au lieu de la valeur aberrante. Sinon, la ou les valeurs aberrantes sont simplement supprimées.
median Si la valeur est TRUE, la médiane est utilisée au lieu de la moyenne dans le remplacement des valeurs aberrantes. opposé si mis à TRUE, donne la valeur opposée (si la plus grande valeur a une différence maximale par rapport à la moyenne, elle donne la plus petite et vice versa) "

Peyman
la source
Cela semble génial, mais si vous avez une colonne de série chronologique dans votre bloc de données, cela change la série chronologique.
PeyM87
7
x<-quantile(retentiondata$sum_dec_incr,c(0.01,0.99))
data_clean <- data[data$attribute >=x[1] & data$attribute<=x[2],]

Je trouve cela très facile de supprimer les valeurs aberrantes. Dans l'exemple ci-dessus, j'extrais simplement 2 percentile à 98 percentile des valeurs d'attribut.

Gaurav Khare
la source
5

Ne serait pas:

z <- df[df$x > quantile(df$x, .25) - 1.5*IQR(df$x) & 
        df$x < quantile(df$x, .75) + 1.5*IQR(df$x), ] #rows

accomplir cette tâche assez facilement?

d8aninja
la source
4

En ajoutant à la suggestion de @sefarkas et en utilisant le quantile comme seuil, on pourrait explorer l'option suivante:

newdata <- subset(mydata,!(mydata$var > quantile(mydata$var, probs=c(.01, .99))[2] | mydata$var < quantile(mydata$var, probs=c(.01, .99))[1]) ) 

Cela supprimera les points points au-delà du 99e quantile. Des précautions doivent être prises comme ce que disait aL3Xa au sujet du maintien des valeurs aberrantes. Il ne doit être supprimé que pour obtenir une autre vue conservatrice des données.

KarthikS
la source
est-ce 0.91ou 0.99? comme mydata$var < quantile(mydata$var, probs=c(.01, .91))[1])oumydata$var < quantile(mydata$var, probs=c(.01, .99))[1])
Komal Rathi
Si vous avez une raison spécifique d'utiliser le 91e centile au lieu du 99e centile, vous pouvez l'utiliser. Ce n'est qu'une heuristique
KarthikS
1

Une façon de faire est

my.NEW.data.frame <- my.data.frame[-boxplot.stats(my.data.frame$my.column)$out, ]

ou

my.high.value <- which(my.data.frame$age > 200 | my.data.frame$age < 0) 
my.NEW.data.frame <- my.data.frame[-my.high.value, ]
Seyma Kalay
la source
0

Les valeurs aberrantes sont assez similaires aux pics, de sorte qu'un détecteur de pics peut être utile pour identifier les valeurs aberrantes. La méthode décrite ici a de très bonnes performances en utilisant les scores z. L'animation située en bas de la page illustre la méthode de signalisation des valeurs aberrantes ou des pics.

Les pics ne sont pas toujours les mêmes que les valeurs aberrantes, mais ils sont souvent similaires.

Un exemple est présenté ici: Cet ensemble de données est lu à partir d'un capteur via des communications série. Des erreurs de communication série occasionnelles, des erreurs de capteur ou les deux conduisent à des points de données répétés et clairement erronés. Il n'y a pas de valeur statistique sur ces points. Ce ne sont sans doute pas des valeurs aberrantes, ce sont des erreurs. Le détecteur de pic de score z a pu signaler des points de données parasites et a généré un ensemble de données résultant propre:entrez la description de l'image ici

Marc Compère
la source
-1

Essaye ça. Nourrissez votre variable dans la fonction et enregistrez le o / p dans la variable qui contiendrait les valeurs aberrantes supprimées

outliers<-function(variable){
    iqr<-IQR(variable)
    q1<-as.numeric(quantile(variable,0.25))
    q3<-as.numeric(quantile(variable,0.75))
    mild_low<-q1-(1.5*iqr)
    mild_high<-q3+(1.5*iqr)
    new_variable<-variable[variable>mild_low & variable<mild_high]
    return(new_variable)
}
Adipta Biwas
la source
Veuillez ajouter quelques explications à votre réponse. Reportez-vous à Comment répondre .
ejderuby