2012-10-12 30 views
6

ho un frame di dati come questo:calcolano i valori anomali in R

x

Team 01/01/2012 01/02/2012 01/03/2012 01/01/2012 01/04/2012 SD Mean 
A  100   50   40  NA   30  60 80 

mi piace per eseguire calcoli su ogni cella per la media e deviazione standard per calcolare i valori anomali. Ad esempio,

abs(x-Mean) > 3*SD 

x$count<-c(1) (incrementare questo valore se la condizione di cui sopra è soddisfatta).

Sto facendo questo per controllare l'anomalia nel mio set di dati. Se conosco i nomi delle colonne, sarebbe più semplice fare i calcoli, ma il numero delle colonne varierà. Alcune celle potrebbero avere NA in esse.

mi piace sottotraccia significa da ciascuna cella, e ho provato questo

x$diff<-sweep(x, 1, x$Mean, FUN='-') 

non sembra funzionare, tutte le idee?

+1

Se ci fornirete con un po 'di esempio dati con 'dput (head (x))', quindi possiamo semplicemente tagliarlo e incollarlo nei nostri browser, e testare le nostre soluzioni. – nograpes

risposta

30

Ottieni il tuo IQR (intervallo interquartile) e più basso quartile/superiore utilizzando:

lowerq = quantile(data)[2] 
upperq = quantile(data)[4] 
iqr = upperq - lowerq #Or use IQR(data) 

Calcola i limiti per un outlier mite:

mild.threshold.upper = (iqr * 1.5) + upperq 
mild.threshold.lower = lowerq - (iqr * 1.5) 

Qualsiasi dato punto al di fuori (> mild.threshold. superiore o < mild.threshold.lower) questi valori sono lievemente anomali

Per rilevare i valori anomali estremi, fare lo stesso, ma moltiplicare per 3 invece:

extreme.threshold.upper = (iqr * 3) + upperq 
extreme.threshold.lower = lowerq - (iqr * 3) 

Qualsiasi dato punto al di fuori (> extreme.threshold.upper o < extreme.threshold.lower) questi valori è un outlier estrema

Spero che questo aiuti

edit: stava accedendo 50%, non al 75%

+3

Dovrebbe essere 'upperq = quantile (data) [4]' – Ben

+0

Questo sarà un algoritmo molto pessimo. Ad esempio, prendere un vettore abbastanza grande in cui dire che l'80% dei punti di dati sono in un intervallo breve (ad esempio 10-100) e il resto del 20% è molto scarso allora questo algoritmo identificherà un numero enorme di valori anomali, che potrebbero non dare un vero senso dei valori anomali nella popolazione – Bg1850

+2

La risposta data qui è un approccio noto a causa di Tukey. Vedi: https://en.wikipedia.org/wiki/Outlier#Tukey.27s_test – stackoverflowuser2010

3

Ho visto che hai fatto alcune domande sul fare le cose per fila. Dovresti evitarlo. R segue il concetto che le colonne rappresentano le variabili e le righe rappresentano le osservazioni. Molte funzioni sono ottimizzate secondo questo concetto. Se hai bisogno di un output ampio o trasposto in un file puoi riorganizzare i tuoi dati prima di scrivere sul file.

Suppongo che i tuoi dati sembrino effettivamente come mostrato nella domanda, ma che tu abbia più di una riga.

df <- read.table(text="Team 01/01/2012 01/02/2012 01/03/2012 01/01/2012 01/04/2012 SD 

Mean 
A  100   50   40  NA   30  60 80 
B  200   40   5   8   NA  NA NA",check.names = FALSE,header=TRUE) 

#needed because one date appears twice 
df <- df[,] 

#reshape the data 
library(reshape2) 
df <- melt(df,id="Team") 
names(df)[2] <- "Date" 

#remove the SD and Mean 
df <- df[!df$Date %in% c("SD","Mean"),] 

#function to detect outliers 
outfun <- function(x) { 
    abs(x-mean(x,na.rm=TRUE)) > 3*sd(x,na.rm=TRUE) 
} 

#test if function works 
outfun(c(200,rnorm(10))) 

#use function over all data 
df3$outlier.all <- outfun(df3$value) 

#apply function for each team 
library(plyr) 
df3 <- ddply(df3,.(Team),transform,outlier.team=outfun(value)) 

Risultato:

  Date Team value outlier.all outlier.team 
1 01/01/2012 A 100  FALSE  FALSE 
2 01/02/2012 A 50  FALSE  FALSE 
3 01/03/2012 A 40  FALSE  FALSE 
4 01/01/2012.1 A NA   NA   NA 
5 01/04/2012 A 30  FALSE  FALSE 
6 01/01/2012 B 200  FALSE  FALSE 
7 01/02/2012 B 40  FALSE  FALSE 
8 01/03/2012 B  5  FALSE  FALSE 
9 01/01/2012.1 B  8  FALSE  FALSE 
10 01/04/2012 B NA   NA   NA 
+0

Ciao @Roland. Grazie per la vostra risposta. Questo è un caso speciale in cui ho migliaia di osservazioni (righe), che mi piacerebbe scoprire i valori anomali e quindi solo grafico. Sto trasformando le date in righe e cercando di controllare ogni cella rispetto alla media e contare il numero di volte in cui ha raggiunto quel punto esterno. Quindi, selezionerò 10 o 20 elementi e li grafici. Fondamentalmente, sto cercando di catturare gli anamoli nel mio set di dati. – user1471980

+0

@ user1471980, beh, la mia risposta è un punto di partenza per farlo. In realtà non è difficile da fare in R (a condizione che i dati siano in formato lungo e ho dimostrato come ottenerli). A seconda del numero di osservazioni (si scrivono migliaia ma potrebbe anche significare centinaia di migliaia) e di gruppi di dati, altri approcci potrebbero essere preferibili considerando il tempo di calcolo. Ma faresti meglio a fare una nuova domanda fornendo tutte le informazioni incluso il tuo obiettivo finale se la mia risposta non è sufficiente. – Roland

+0

grazie per l'input. Come da tua raccomandazione, ho creato un'altra domanda, spero di averlo fatto - http://stackoverflow.com/questions/12888212/detecting-outliers-on-wide-data-frame – user1471980

4

Ho usato @ risposta di by0 sopra per creare una funzione che rimuove automaticamente i valori anomali.Ecco la funzione e qualche esempio di codice:

# generate 10 random numbers and 2 'outlier' numbers 
testData <- c(-42,rnorm(10),42) 

# show the numbers 
testData 

# define a function to remove outliers 
FindOutliers <- function(data) { 
    lowerq = quantile(data)[2] 
    upperq = quantile(data)[4] 
    iqr = upperq - lowerq #Or use IQR(data) 
    # we identify extreme outliers 
    extreme.threshold.upper = (iqr * 3) + upperq 
    extreme.threshold.lower = lowerq - (iqr * 3) 
    result <- which(data > extreme.threshold.upper | data < extreme.threshold.lower) 
} 

# use the function to identify outliers 
temp <- FindOutliers(testData) 

# remove the outliers 
testData <- testData[-temp] 

# show the data with the outliers removed 
testData 
0

le seguenti formule potrebbero essere utilizzati per determinare quali valori sono valori erratici:

upper.outlier.calc <- function(x.var, df){with(df, quantile(x.var, 0.75) + (1.5 * (quantile(x.var, 0.75) - quantile(x.var, 0.25))))}

lower.outlier.calc <- function(x.var, df){with(df, quantile(x.var, 0.25) - (1.5 * (quantile(x.var, 0.75) - quantile(x.var, 0.25))))}

Problemi correlati