Preprocesamiento (Volumen III)


Missing Values (Valores faltantes)

Santiago Banchero
Leo Lucianna
Juan Manuel Fernandez

Minería de Datos - UBA

Contenidos

Vamos a trabajar en la implementación de las siguientes técnicas en R:

  • Missing Values (Valores Faltantes)
    • Análisis de Faltantes
    • Registros completos
    • Imputaciones (Media, Regresiones, Hot deck)
    • Multiple Imputation by Chained Equations (MICE)
    • Análisis gráfico de los métodos de imputación

Análisis de Faltantes

Cargamos iris y generamos datos faltantes aleatoriamente:

for(i in 1:4) {
  for(j in 1:5) {
    inst.aleat<-sample(1:nrow(iris), 1, replace=F)
    iris[inst.aleat, i]<-NA
  }
}

Podemos ver, por ejemplo, las instancias con que poseen faltante en una variable:

iris[is.na(iris$Sepal.Length),]
    Sepal.Length Sepal.Width Petal.Length Petal.Width    Species
22            NA         3.7          1.5         0.4     setosa
65            NA         2.9          3.6         1.3 versicolor
67            NA         3.0          4.5         1.5 versicolor
90            NA         2.5          4.0         1.3 versicolor
149           NA         3.4          5.4         2.3  virginica

Análisis de Faltantes (++)


Podríamos contar la cantidad de faltantes para una variable:

sum(is.na(iris$Sepal.Length))
[1] 5


También podemos analizar la proporción de faltantes sobre el total de instancias:

round(sum(is.na(iris$Sepal.Length))/nrow(iris)*100,2)
[1] 3.33

Valores Faltantes: Registros Completos

Si quisieramos trabajar únicamente con las instancias del dataset con registros completos:

iris.reg_completos<-na.omit(iris)
nrow(iris.reg_completos)
[1] 131

Simplemente podemos realizar los cálculos removiendo los faltantes:

print(mean(iris$Petal.Length))
[1] NA
print(mean(iris$Petal.Length, na.rm = TRUE))
[1] 3.8

Valores Faltantes: Imputación por la Media


Seleccionamos las instancias con valor faltante y las reemplazamos por la media de ese atributo:

# Sustitución por la media
iris.imp<-iris
iris.imp$media<-iris$Sepal.Length

iris.imp$media[is.na(iris.imp$media)]<-mean(iris.imp$media, na.rm = TRUE)

# Verificamos que no quedan faltantes
sum(is.na(iris.imp$media))
[1] 0

Valores Faltantes: Imputación por Regresión

Primero ajustamos el modelo de Regresión:

#Armamos el modelo
rl_model<-lm(iris.imp$Sepal.Length ~ iris.imp$Sepal.Width+iris.imp$Petal.Length, data = iris.imp)

# Imprimimos los coeficientes del modelo
print(rl_model$coefficients)
          (Intercept)  iris.imp$Sepal.Width iris.imp$Petal.Length 
            2.2458828             0.6038898             0.4719438 

Luego, con la instrucción summary tenemos un resumen con los coeficientes y la eficiencia del modelo ajustado, entre otras cosas

summary(rl_model)

Valores Faltantes: Imputación por Regresión (++)

Analizamos el modelo:


Call:
lm(formula = iris.imp$Sepal.Length ~ iris.imp$Sepal.Width + iris.imp$Petal.Length, 
    data = iris.imp)

Residuals:
     Min       1Q   Median       3Q      Max 
-0.97935 -0.22927 -0.00269  0.22184  0.76359 

Coefficients:
                      Estimate Std. Error t value Pr(>|t|)    
(Intercept)            2.24588    0.26100   8.605 1.97e-14 ***
iris.imp$Sepal.Width   0.60389    0.07291   8.283 1.18e-13 ***
iris.imp$Petal.Length  0.47194    0.01812  26.038  < 2e-16 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 0.335 on 132 degrees of freedom
  (15 observations deleted due to missingness)
Multiple R-squared:  0.839, Adjusted R-squared:  0.8366 
F-statistic:   344 on 2 and 132 DF,  p-value: < 2.2e-16

Valores Faltantes: Imputación por Regresión (+++)

Ahora, solo queda imputar los valores faltantes en función del modelo generado:

# Imputamos en base al modelo
iris.imp$regresion<-iris.imp$Sepal.Length

SW<-iris.imp$Sepal.Width[is.na(iris.imp$Sepal.Length)]
PL<-iris.imp$Petal.Length[is.na(iris.imp$Sepal.Length)]
coef<-rl_model$coefficients

# Hacemos la imputación
iris.imp$regresion[is.na(iris.imp$regresion)]<-coef[1]+SW*coef[2]+PL*coef[3]

# Verificamos que no existen faltantes
sum(is.na(iris.imp$regresion))
[1] 0

Valores Faltantes: Imputación Hot Deck

Para hot deck, vamos a utilizar la librería VIM. La función hotdeck imputará los datos directamente sobre el atributo del parámetro y generará un nuevo atributo -boolean- que indica las instancias imputadas:

# Cargamos la librería
library(VIM)

# Definimos un dataframe auxiliar para no perder la variable original
df_aux<-hotdeck(iris, variable="Sepal.Length")
iris.imp$hotdeck<-df_aux$Sepal.Length
iris.imp$hotdeckbool<-df_aux$Sepal.Length_imp

# Verificamos que no existen faltantes
sum(is.na(iris.imp$hotdeck))
[1] 0

Multiple Imputation by Chained Equations (MICE)

Vamos a trabajar con MICE, esta librería provee un gráfico que detalla la cantidad de atributos con missing por cada atributo:

# Cargamos la librería
library(mice)
# Gráfico con el resumen de los missing para el dataset iris
md.pattern(iris, rotate.names=TRUE)

plot of chunk unnamed-chunk-13

    Species Sepal.Length Sepal.Width Petal.Length Petal.Width   
131       1            1           1            1           1  0
4         1            1           1            1           0  1
4         1            1           1            0           1  1
1         1            1           1            0           0  2
5         1            1           0            1           1  1
5         1            0           1            1           1  1
          0            5           5            5           5 20

MICE (++)

Ahora avanzamos sobre la imputación:

# Imputamos los datos con pmm (media, para valores numéricos)
imputed_Data <- mice(iris, maxit = 3, method = 'pmm')

 iter imp variable
  1   1  Sepal.Length  Sepal.Width  Petal.Length  Petal.Width
  1   2  Sepal.Length  Sepal.Width  Petal.Length  Petal.Width
  1   3  Sepal.Length  Sepal.Width  Petal.Length  Petal.Width
  1   4  Sepal.Length  Sepal.Width  Petal.Length  Petal.Width
  1   5  Sepal.Length  Sepal.Width  Petal.Length  Petal.Width
  2   1  Sepal.Length  Sepal.Width  Petal.Length  Petal.Width
  2   2  Sepal.Length  Sepal.Width  Petal.Length  Petal.Width
  2   3  Sepal.Length  Sepal.Width  Petal.Length  Petal.Width
  2   4  Sepal.Length  Sepal.Width  Petal.Length  Petal.Width
  2   5  Sepal.Length  Sepal.Width  Petal.Length  Petal.Width
  3   1  Sepal.Length  Sepal.Width  Petal.Length  Petal.Width
  3   2  Sepal.Length  Sepal.Width  Petal.Length  Petal.Width
  3   3  Sepal.Length  Sepal.Width  Petal.Length  Petal.Width
  3   4  Sepal.Length  Sepal.Width  Petal.Length  Petal.Width
  3   5  Sepal.Length  Sepal.Width  Petal.Length  Petal.Width

MICE (+++)

Cuales son los métodos de imputación del paquete MICE?

plot of chunk unnamed-chunk-15

MICE (++++)

Ahora, con la función complete recuperamos los datos completos:

#Tomamos los datos completos
completeData <- complete(imputed_Data)

# Los asignamos a una nueva variable
iris.imp$mice <- completeData$Sepal.Length

# Verificamos que no existen faltantes
sum(is.na(iris.imp$mice))
[1] 0

Análisis Gráfico de los métodos de imputación

Ahora, analizamos gráficamente la distribución original y su variación luego de realizar las imputaciones:

# Quitamos los atributos que no vamos a usar y renombramos Sepal.Length
iris.imp<-iris.imp[,-c(2:5)]
names(iris.imp)[1]<-"original"

# Analisis grafico de los resultados
plot(density(iris.imp$original, na.rm=TRUE), type = "l", col="red", ylab = "Original", ylim=c(0,0.5))
lines(density(iris.imp$media, na.rm=TRUE), type = "l", col="blue")
lines(density(iris.imp$regresion, na.rm=TRUE), type = "l", col="green")
lines(density(iris.imp$hotdeck, na.rm=TRUE), type = "l", col="yellow")
lines(density(iris.imp$mice, na.rm=TRUE), type = "l", col="black")
legend(7, 0.5, legend=c("Original", "Media", 'Regresión', 'Hotdeck', 'MICE'), col=c("red", "blue", 'green','yellow', "black"), lty=1, cex=0.8)

Análisis Gráfico de los métodos de imputación (++)

Obtenemos los siguientes gráficos de densidad:

plot of chunk unnamed-chunk-18