2012-10-12 141 views
6

I tienen una trama de datos como esta:el cálculo de los valores atípicos en 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 

me gusta para llevar a cabo el cálculo en cada célula para la media y la SD para calcular los valores atípicos. Por ejemplo,

abs(x-Mean) > 3*SD 

x$count<-c(1) (incrementar este valor si se cumple la condición anterior).

Estoy haciendo esto para verificar la anomalía en mi conjunto de datos. Si conozco los nombres de las columnas, sería más fácil hacer los cálculos, pero el número de columnas variará. Algunas celdas pueden tener NA en ellas.

me gusta Subtrack media de cada célula, y probé este

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

no parece estar funcionando, alguna idea?

+1

Si nos proporciona con una pequeña muestra datos con 'dput (head (x))', luego podemos cortar y pegarlo en nuestros navegadores, y probar nuestras soluciones. – nograpes

Respuesta

30

Obtenga su RIC (rango intercuartil) y el cuartil inferior/superior usando:

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

Calcular los límites de un valor atípico leve:

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

Cualquier dato punto exterior (> mild.threshold. upper o < mild.threshold.lower) estos valores son un valor atípico leve

Para detectar extremos extremos haga lo mismo, pero multiplique por 3 en su lugar:

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

Cualquier dato punto exterior (> extreme.threshold.upper o < extreme.threshold.lower) estos valores es un valor atípico extremo

Esperanza esto ayuda

edición: estaba accediendo a un 50%, no 75%

+3

Debe ser 'upperq = quantile (data) [4]' – Ben

+0

Esto va a ser un algoritmo muy malo. Por ejemplo, tome un vector bastante grande donde digamos que el 80% de los puntos de datos están en un rango corto (por ejemplo, 10-100) y el resto el 20% son muy escasos, entonces este algoritmo identificará una gran cantidad de valores atípicos, lo que puede no dar un verdadero sentido de los valores atípicos en la población – Bg1850

+2

La respuesta dada aquí es un enfoque bien conocido debido a Tukey. Ver: https://en.wikipedia.org/wiki/Outlier#Tukey.27s_test – stackoverflowuser2010

3

He visto que ha hecho algunas preguntas sobre cómo hacer las cosas por fila. Deberías evitar eso. R sigue el concepto de que las columnas representan variables y las filas representan observaciones. Muchas funciones se optimizan de acuerdo con este concepto. Si necesita una salida amplia o transpuesta a un archivo, puede reorganizar sus datos justo antes de escribir en el archivo.

Supongo que sus datos realmente se ven como se muestra en la pregunta, pero que tiene más de una fila.

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

Resultado:

  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

Hola @Roland. Gracias por su respuesta. Este es un caso especial en el que tengo miles de observaciones (filas), que me gustaría descubrir los valores atípicos y luego graficarlos solo. Estoy transformando las fechas en filas e intentando verificar cada celda contra la media y el número de veces que llegó a ese punto atípico. Luego, escogeré 10 o 20 de los artículos y los representaré gráficamente. Básicamente, estoy tratando de detectar las anomalías en mi conjunto de datos. – user1471980

+0

@ user1471980, bueno, mi respuesta es un punto de partida para hacer esto. En realidad no es difícil de hacer en R (siempre que los datos estén en formato largo y demostré cómo lograr eso). Dependiendo de la cantidad de observaciones (usted escribe miles, pero eso también podría significar cientos de miles) y grupos de datos, otros enfoques podrían ser preferibles teniendo en cuenta el tiempo de cálculo. Pero será mejor que haga una nueva pregunta que contenga toda la información, incluido su objetivo final, si mi respuesta no es suficiente. – Roland

+0

gracias por su aporte. De acuerdo con su recomendación, sí creé otra pregunta, con suerte he destacado: http://stackoverflow.com/questions/12888212/detecting-outsliers-on-wide-data-frame – user1471980

4

he utilizado @ respuesta de by0 arriba para crear una función que elimina automáticamente los valores atípicos.Esta es la función y un código de ejemplo:

# 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

Las siguientes fórmulas se podrían utilizar para determinar qué valores son los valores extremos:

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

Cuestiones relacionadas