Preprocesamiento (Volumen II)

Detección de outliers (valores anómalos)


Santiago Banchero
Leo Lucianna
Juan Manuel Fernandez

Minería de Datos - UBA

Contenidos

  • Análisis gráfico de outliers
  • Técnicas de detección y tratamiento de outliers
  • Técnicas univariadas:
    • Rango intercuartil
    • Desvíos de la media
    • Z-score
  • Técnicas multivariadas:
    • Detección de outliers mediante Local Outlier Factor (LOF)
    • Detección de outliers mediante Mahalanobis

Limpieza de datos: Detección de Outliers

Busquemos outliers en el atributo Road_55db del dataset ruidoso:

ruidoso=read.csv('ruidoso.txt')
data = ruidoso$Road_55dB
plot(data)

plot of chunk unnamed-chunk-2

Hay outliers? Cuales?

Análisis del atributo ruidoso$Road_55dB

Observemos analíticamente la distribución de la variable:
Media:

mean(data)
[1] 159228.8

Mínimo:

min(data)
[1] 7600

Máximo:

max(data)
[1] 3108200

Detección de outliers: Análisis gráfico (++)

Mediante boxplot podemos observar gráficamente la distribución de la variable:

plot of chunk unnamed-chunk-6

Un criterio de detección de outliers podría ser eliminar los datos que se encuentran por fuera (abajo/arriba) de los “bigotes”.

Análisis del atributo ruidoso$Road_55dB (++)

Observemos gráficamente la distribución de la variable mediante boxplot:

boxplot(data)

plot of chunk unnamed-chunk-7

Claramente, la distribución de la variable no es “normal”, o si? Muchas veces los outliers “esconden” la distribución real de un feature.

Detección de Outliers mediante IRQ

  • Detección de outliers mediante el IRQ*1,5 (Rango intercuartil)
data.riq<-IQR(data)
print(data.riq)
[1] 59950

Calculamos Q1 y Q3:

cuantiles<-quantile(data, c(0.25, 0.5, 0.75), type = 7)
print(cuantiles)
  25%   50%   75% 
18950 37550 78900 

Detección de Outliers mediante IRQ (++)

Multiplicamos el cuantil 1 por 1.5 para determinar la barrera MENOR para la detección de outliers:

outliers_min<-as.numeric(cuantiles[1])-1.5*data.riq
print(outliers_min)
[1] -70975

Y multiplicamos el cuantil 1 por 1.5 para determinar la barrera MAYOR para la detección de outliers:

outliers_max<-as.numeric(cuantiles[3])+1.5*data.riq
print(outliers_max)
[1] 168825

Detección de Outliers mediante IRQ (+++)

Otra opción mas sencilla es utilizar el objeto boxplot:

bp = boxplot(data)

plot of chunk unnamed-chunk-12





out_inf = bp$stats[1]
out_sup = bp$stats[5]

cat("Extremo inferior", out_inf)
Extremo inferior 7600
cat("Extremo superior", out_sup)
Extremo superior 166400

Ruidoso$Road_55dB "sin" outliers

plot(sort(data[data>outliers_min & data<outliers_max]))

plot of chunk unnamed-chunk-14

boxplot(data[data>outliers_min & data<outliers_max], decreasing = FALSE)

plot of chunk unnamed-chunk-15

Detección de Outliers mediante Desvíos de la Media

Otra alternativa es realizar detección de outliers utilizando alguna medida de tendencia central.

Detección por N desvíos de la media (En el ejemplo N=3):

N=3
data<-ruidoso$Road_55dB
desvio<-sd(data)
print(desvio)
[1] 484751.3
outliers_max<-mean(data)+N*desvio
print(outliers_max)
[1] 1613483
outliers_min<-mean(data)-N*desvio
print(outliers_min)
[1] -1295025

Ruidoso$Road_55dB "sin" outliers

plot(sort(data[data>outliers_min & data<outliers_max], decreasing = FALSE))

plot of chunk unnamed-chunk-19

boxplot(sort(data[data>outliers_min & data<outliers_max], decreasing = FALSE))

plot of chunk unnamed-chunk-20

Detección de Outliers mediante Z-Score

Otra variante es trabajar a través de la métrica de z-score:
Cálculo de Z-Score:

data<-ruidoso
data$zscore<-(data$Road_55dB-mean(data$Road_55dB))/sd(data$Road_55dB)
umbral<-2
max(data$zscore)
[1] 6.083473
min(data$zscore)
[1] -0.3127971

Ruidoso$Road_55dB "sin" outliers

plot(sort(data$Road_55dB[data$zscore<umbral], decreasing = FALSE))

plot of chunk unnamed-chunk-24

boxplot(sort(data$Road_55dB[data$zscore<umbral], decreasing = FALSE))

plot of chunk unnamed-chunk-25

Detección de Outliers: Técnicas multivariadas

library(scatterplot3d)
library(readr)
data <- read_csv("forestfires.csv")
data <- data[,c(7,9,10)]
scatterplot3d(data$DC, data$temp, data$RH)

plot of chunk unnamed-chunk-26

Local Outlier Factor


Ahora abordamos, Local Outlier Factor [1] que es una técnica multivariada, dado que tiene en cuenta varios atributos para la detección del outlier. La idea es calcular un score para cada instancia, el cual representa un “índice” de densidad con respecto a los K vecinos mas cercanos.

# Cargamos la librería
library(Rlof)
# Calculamos LOF para k=3 vecinos por instancia
data$score<-lof(data, k=3)
umbral<-4
data$outlier <- (data$score>umbral)
data <- na.omit(data)


[1] https://cran.r-project.org/web/packages/Rlof/Rlof.pdf

Outliers: LOF (++)

data$color <- ifelse(data$outlier, "red", "black")
scatterplot3d(data$DC, data$temp, data$RH, color = data$color)

plot of chunk unnamed-chunk-28

Distancia de Mahalanobis

Por último, utilizamos la distancia de Mahalanobis. Se trata de una medida de distancia que, normalizando por la matriz de covarianza, toma en cuenta la correlación entre las variables.

data$mahalanobis <- mahalanobis(data[,1:3], colMeans(data[,1:3]), cov(data[,1:3]))

# Ordenamos de forma decreciente, según el score de Mahalanobis
data <- data[order(data$mahalanobis,decreasing = TRUE),]

# Descartamos los outliers según un umbral
umbral<-8
data$outlier <- (data$mahalanobis>umbral)

Outliers: Distancia de Mahalanobis (++)

data$color <- ifelse(data$outlier, "red", "black")
scatterplot3d(data$DC, data$temp, data$RH, color = data$color)

plot of chunk unnamed-chunk-30