Come rimuovere i valori anomali da un set di dati


98

Ho alcuni dati multivariati di bellezza e età. L'età varia da 20 a 40 a intervalli di 2 (20, 22, 24 .... 40) e per ogni registrazione di dati viene assegnata un'età e una valutazione di bellezza da 1-5. Quando eseguo grafici a scatole di questi dati (età sull'asse X, valutazioni di bellezza sull'asse Y), ci sono alcuni valori anomali tracciati fuori dai baffi di ogni riquadro.

Voglio rimuovere questi valori anomali dal data frame stesso, ma non sono sicuro di come R calcoli i valori anomali per i suoi box plot. Di seguito è riportato un esempio di come potrebbero apparire i miei dati. inserisci qui la descrizione dell'immagine


2
La boxplotfunzione restituisce i valori anomali (tra le altre statistiche) in modo invisibile. Prova a foo <- boxplot(...); fooleggere ?boxplotper capire l'output.
Joshua Ulrich

Dovresti modificare la tua domanda in base al commento che hai dato alla risposta di @ Prasad!
aL3xa

@ aL3xa: è nella prima frase del secondo paragrafo.
Joshua Ulrich


Potete inviare un collegamento ai dati?
parole per il

Risposte:


120

OK, dovresti applicare qualcosa di simile al tuo set di dati. Non sostituire e salvare o distruggerai i tuoi dati! E, a proposito, non dovresti (quasi) mai rimuovere i valori anomali dai tuoi dati:

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
}

Per vederlo in azione:

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

E ancora una volta, non dovresti mai farlo da solo, i valori anomali sono solo destinati a esserlo! =)

EDIT: ho aggiunto na.rm = TRUEcome predefinito.

EDIT2:quantile funzione rimossa , aggiunta di pedici, quindi resa più veloce! =)

inserisci qui la descrizione dell'immagine


Grazie per l'aiuto! Penserei che se R fosse in grado di emettere i valori anomali nel boxplot, non dovrei fare questi calcoli intermedi. Per quanto riguarda l'eliminazione dei valori anomali, questo è solo per un incarico.
Dan Q

3
OK, mi manca qualcosa qui. Vuoi rimuovere i valori anomali dai dati, in modo da poterli tracciare con boxplot. È gestibile, e dovresti contrassegnare la risposta di @ Prasad allora, poiché ha risposto alla tua domanda. Se si desidera escludere valori anomali utilizzando la "regola dei valori anomali" q +/- (1.5 * H), quindi eseguire alcune analisi, utilizzare questa funzione. A proposito, l'ho fatto da zero, senza cercare su Google, quindi c'è una possibilità che abbia reinventato la ruota con questa mia funzione ...
aL3xa

10
Non dovresti fare domande sui compiti su StackOverflow!
Hadley

7
Ciò significa che non dovremmo rispondere neanche noi? =)
aL3xa

5
"valori anomali sono solo destinati ad essere"? Non necessariamente. Possono derivare da errori di misura e devono essere esaminati accuratamente. Quando il valore anomalo è troppo grande, può significare qualcosa, o non così tanto. Ecco perché (almeno in biologia) la mediana di solito dice di più su una popolazione rispetto alla media.
Rodrigo

133

Nessuno ha pubblicato la risposta più semplice:

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

Vedi anche questo: http://www.r-statistics.com/2011/01/how-to-label-all-the-outliers-in-a-boxplot/


4
Davvero elegante. Grazie. Ma bisogna fare attenzione se la distribuzione ha più di una modalità e gli outlier sono davvero pochi e sparsi.
KarthikS

Sarebbe stato fantastico se tu fossi in grado di ottenere l'indice di loro in un set di dati. Il modo in cui hai finito filtrerà in base al valore dei dati. Se anche il box plot esegue il raggruppamento, non necessariamente lo stesso valore dei dati sarà anomalo in ciascun gruppo
adam

2
È anche importante ricordare che non modifica il set di dati. Questo è solo un metodo di filtraggio. Quindi, se intendi utilizzare il set di dati senza valori anomali, assegnalo a una variabile. ad esempioresult = x[!x %in% boxplot.stats(x)$out]
Victor Augusto

Avere solo una riga di codice non significa necessariamente che sia semplice! Non è sempre facile capire un codice di una riga, specialmente per i principianti e senza commenti.
PeyM87

29

Usalo outline = FALSEcome opzione quando esegui il boxplot (leggi la guida!).

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

inserisci qui la descrizione dell'immagine


4
in effetti, questo rimuoverà i valori anomali dal boxplot stesso, ma voglio rimuovere i valori anomali dal frame di dati.
Dan Q

2
Capisco, quindi come ha detto @Joshua è necessario guardare i dati restituiti dalla funzione boxplot (in particolare gli elementi oute groupnell'elenco).
Prasad Chalasani

16

La funzione boxplot restituisce i valori utilizzati per eseguire il tracciamento (che in realtà viene eseguito da 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

Di proposito non ho risposto alla domanda specifica perché ritengo che sia un malcostume statistico rimuovere i "valori anomali". Considero una pratica accettabile non tracciarli in un grafico a scatole, ma rimuoverli solo perché superano un certo numero di deviazioni standard o un certo numero di larghezze interquartili è una manipolazione sistematica e non scientifica della registrazione osservativa.


4
Ebbene, eludere la domanda senza sapere perché la domanda è stata posta non è nemmeno una buona pratica. Sì, non è opportuno rimuovere i "valori anomali" dai dati, ma a volte sono necessari i dati senza valori anomali per attività specifiche. In un compito di statistica che ho avuto di recente, abbiamo dovuto visualizzare un insieme senza i suoi valori anomali per determinare il miglior modello di regressione da utilizzare per i dati. Quindi là!
Alex Essilfie

4
Non sto considerando il consiglio che potresti aver ricevuto a questo proposito di "determinare il miglior modello di regressione" per essere particolarmente persuasivo. Invece, se hai bisogno di rimuovere i valori anomali per quello scopo dichiarato vagamente, penso che si rifletta male sulle persone che lo hanno consigliato piuttosto che essere la prova dell'invalidità della mia posizione.
IRTFM

Immagino sia legittimo quando sai che stai rimuovendo il "rumore". soprattutto nei dati fisiologici.
roscoe1895

Sì. Se hai buone ragioni per credere che un processo separato crei il segnale, è una giustificazione per la rimozione dai dati.
IRTFM

9

Ho cercato pacchetti relativi alla rimozione dei valori anomali e ho trovato questo pacchetto (sorprendentemente chiamato "valori anomali"!): Https://cran.r-project.org/web/packages/outliers/outliers.pdf
se lo esamini tu vedere diversi modi per rimuovere i valori anomali e tra questi ho trovato quello rm.outlierpiù comodo da usare e come dice il link sopra: "Se il valore anomalo viene rilevato e confermato da test statistici, questa funzione può rimuoverlo o sostituirlo con la media o la mediana del campione" e anche qui c'è la parte sull'utilizzo dalla stessa fonte:
" Usage

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

Argomenta
x un set di dati, più frequentemente un vettore. Se l'argomento è un dataframe, il valore anomalo viene rimosso da ogni colonna da sapply. Lo stesso comportamento viene applicato da applicare quando viene fornita la matrice.
fill Se impostato su TRUE, la mediana o la media viene posizionata al posto del valore anomalo. Altrimenti, i valori anomali vengono semplicemente rimossi.
mediana Se impostato su TRUE, nella sostituzione dei valori anomali viene utilizzata la mediana invece della media. opposto se impostato a TRUE, dà il valore opposto (se il valore più grande ha la massima differenza dalla media, dà il più piccolo e viceversa) "


Sembra fantastico, ma se hai una colonna delle serie temporali nel tuo frame di dati, cambia la serie temporale.
PeyM87

7
x<-quantile(retentiondata$sum_dec_incr,c(0.01,0.99))
data_clean <- data[data$attribute >=x[1] & data$attribute<=x[2],]

Trovo che sia molto facile rimuovere i valori anomali. Nell'esempio precedente sto solo estraendo dal 2 al 98 percentile dei valori degli attributi.


5

Non lo farei:

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

svolgere questo compito abbastanza facilmente?


4

Aggiungendo al suggerimento di @sefarkas e usando il quantile come interruzioni, si potrebbe esplorare la seguente opzione:

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

Questo rimuoverà i punti punti oltre il 99 ° quantile. Bisogna fare attenzione a quello che diceva aL3Xa sul mantenere i valori anomali. Dovrebbe essere rimosso solo per ottenere una visualizzazione conservativa alternativa dei dati.


è 0.91o 0.99? come in mydata$var < quantile(mydata$var, probs=c(.01, .91))[1])omydata$var < quantile(mydata$var, probs=c(.01, .99))[1])
Komal Rathi

Se hai un motivo specifico per utilizzare il 91 ° percentile invece del 99 ° percentile, puoi usarlo. È solo un'euristica
KarthikS

1

Un modo per farlo è

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

o

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

0

I valori anomali sono abbastanza simili ai picchi, quindi un rilevatore di picchi può essere utile per identificare i valori anomali. Il metodo qui descritto ha prestazioni abbastanza buone utilizzando i punteggi z. L'animazione nella parte inferiore della pagina illustra il metodo di segnalazione su valori anomali o picchi.

I picchi non sono sempre gli stessi dei valori anomali, ma spesso sono simili.

Di seguito viene mostrato un esempio: questo set di dati viene letto da un sensore tramite comunicazioni seriali. Occasionali errori di comunicazione seriale, errori del sensore o entrambi portano a punti dati ripetuti e chiaramente errati. Non c'è valore statistico in questi punti. Probabilmente non sono valori anomali, sono errori. Il rilevatore di picco z-score è stato in grado di segnalare punti dati spuri e ha generato un set di dati risultante pulito:inserisci qui la descrizione dell'immagine


-1

Prova questo. Inserisci la tua variabile nella funzione e salva l'o / p nella variabile che conterrebbe valori anomali rimossi

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

Per favore aggiungi qualche spiegazione alla tua risposta. Fare riferimento a Come rispondere .
ejderuby
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.