2013-03-01 19 views
5

Ho dati con valori x discreti, comeRimozione valori anomali facilmente in R

x = c(3,8,13,8,13,3,3,8,13,8,3,8,8,13,8,13,8,3,3,8,13,8,13,3,3) 
y = c(4,5,4,6,7,20,1,4,6,2,6,8,2,6,7,3,2,5,7,3,2,5,7,3,2); 

Come posso generare un nuovo set di valori x ed y dove eliminare coppie di valori in cui il valore y è 2 deviazioni standard sopra la media per quel bin. Ad esempio, nel contenitore x = 3, 20 è più di 2 SD sopra la media, in modo tale che il punto dati debba essere rimosso.

risposta

6

per me si desidera qualcosa di simile:

by(dat,dat$x, function(z) z$y[z$y < 2*sd(z$y)]) 
dat$x: 3 
[1] 4 1 6 5 7 3 2 
--------------------------------------------------------------------------------------------------------------- 
dat$x: 8 
[1] 4 2 2 2 3 
--------------------------------------------------------------------------------------------------------------- 
dat$x: 13 
[1] 3 2 

EDIT dopo il commento:

by(dat,dat$x, 
      function(z) z$y[abs(z$y-mean(z$y))< 2*sd(z$y)]) 

EDIT

ho un po 'cambiare la by fu nction per ottenere x e y, poi chiamo rbind utilizzando do.call

do.call(rbind,by(dat,dat$x,function(z) { 
           idx <- abs(z$y-mean(z$y))< 2*sd(z$y) 
           z[idx,] 
      })) 

o utilizzando plyr in unica convocazione

ddply(dat,.(x),function(z) { 
       idx <- abs(z$y-mean(z$y))< 2*sd(z$y) 
        z[idx,]}) 
+1

dovrebbe essere 'z $ y liuminzhao

+0

@liuminzhao penso che tu abbia ragione. – agstudy

+0

@liuminzhao Aggiorno la mia risposta. Penso che il mio errore derivi dalla formulazione della domanda (ho bisogno di migliorare il mio inglese :)) – agstudy

1

Qualcosa di simile?

newdata <- cbind(x,y)[-which(y>2*sd(y)), ] 

O vuoi dire qualcosa del genere?

Data <- cbind(x,y) 
Data[-which(sd(y)>rowMeans(Data)), ] 
+0

Questa soluzione non rimuove valori anomali in 'y' da bin (* vale a dire * separatamente per ogni valore di' x'), bensì su scala globale – QkuCeHBH

+0

destro. Dovrebbe essere fatto dal contenitore .. – CodeGuy

2

È possibile utilizzare tapply per questo, ma si perde la vostra ordinazione originale.

tapply(y,x,function(z) z[abs(z-mean(z))<2*sd(z)]) 
$`3` 
[1] 4 1 6 5 7 3 2 

$`8` 
[1] 5 6 4 2 8 2 7 2 3 5 

$`13` 
[1] 4 7 6 6 3 2 7 
+0

Quindi come posso ristrutturare questo in un elenco di valori xey? – CodeGuy

Problemi correlati