Tratamiento de datos faltantes (Análisis)
Juan Manuel Fernandez
En este video vamos a trabajar en el análisis de datos faltantes:
Vamos a trabajar con un dataset conocido, iris. Vamos a acortar los nombres por comodidad:
names(iris) = c("Sep.L.", "Sep.W.", "Pet.L.", "Pet.W.", "Species")
Aplicamos faltantes aleatoriamente en todos los atributos (en cuanto a cantidad e instancias):
for(i in 1:4) { # Recorremos los atributos numéricos (indices 1-4)
n = sample(1:30, 1) # cantidad de faltantes que generamos por atributo
inst<-sample(1:nrow(iris), n, replace=F) # indice de instancias NA
iris[inst, i]<-NA
cat('Se definen ', n, ' NA en ', names(iris[i]),'(filas: ', inst,').\n')
}
Se definen 2 NA en Sep.L. (filas: 107 121 ).
Se definen 9 NA en Sep.W. (filas: 71 147 131 38 58 53 76 16 128 ).
Se definen 27 NA en Pet.L. (filas: 74 85 122 51 113 92 13 54 138 42 116 8 109 104 123 70 91 99 72 147 80 139 97 82 76 60 90 ).
Se definen 1 NA en Pet.W. (filas: 15 ).
Con la función is.na() podemos verificar que instancias son faltantes:
# Aplicamos a las primeras 10 filas
is.na(iris[1:10,])
Sep.L. Sep.W. Pet.L. Pet.W. Species
1 FALSE FALSE FALSE FALSE FALSE
2 FALSE FALSE FALSE FALSE FALSE
3 FALSE FALSE FALSE FALSE FALSE
4 FALSE FALSE FALSE FALSE FALSE
5 FALSE FALSE FALSE FALSE FALSE
6 FALSE FALSE FALSE FALSE FALSE
7 FALSE FALSE FALSE FALSE FALSE
8 FALSE FALSE TRUE FALSE FALSE
9 FALSE FALSE FALSE FALSE FALSE
10 FALSE FALSE FALSE FALSE FALSE
La función devuelve una máscara con TRUE/FALSE (faltante, no faltante).
Podemos aplicar is.na() a un atributo específico:
is.na(iris$Sep.W)
[1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[13] FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[25] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[37] FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[49] FALSE FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE TRUE FALSE FALSE
[61] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE TRUE FALSE
[73] FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[85] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[97] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[109] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[121] FALSE FALSE FALSE FALSE FALSE FALSE FALSE TRUE FALSE FALSE TRUE FALSE
[133] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[145] FALSE FALSE TRUE FALSE FALSE FALSE
A su vez, podemos ver, por ejemplo, las instancias que poseen faltantes en una variable:
iris[is.na(iris$Sep.W.),]
Sep.L. Sep.W. Pet.L. Pet.W. Species
16 5.7 NA 1.5 0.4 setosa
38 4.9 NA 1.4 0.1 setosa
53 6.9 NA 4.9 1.5 versicolor
58 4.9 NA 3.3 1.0 versicolor
71 5.9 NA 4.8 1.8 versicolor
76 6.6 NA NA 1.4 versicolor
128 6.1 NA 4.9 1.8 virginica
131 7.4 NA 6.1 1.9 virginica
147 6.3 NA NA 1.9 virginica
También podríamos verificar las instancias que poseen faltante en algún atributo:
iris[!complete.cases(iris),]
Sep.L. Sep.W. Pet.L. Pet.W. Species
8 5.0 3.4 NA 0.2 setosa
13 4.8 3.0 NA 0.1 setosa
15 5.8 4.0 1.2 NA setosa
16 5.7 NA 1.5 0.4 setosa
38 4.9 NA 1.4 0.1 setosa
42 4.5 2.3 NA 0.3 setosa
51 7.0 3.2 NA 1.4 versicolor
53 6.9 NA 4.9 1.5 versicolor
54 5.5 2.3 NA 1.3 versicolor
58 4.9 NA 3.3 1.0 versicolor
60 5.2 2.7 NA 1.4 versicolor
70 5.6 2.5 NA 1.1 versicolor
71 5.9 NA 4.8 1.8 versicolor
72 6.1 2.8 NA 1.3 versicolor
74 6.1 2.8 NA 1.2 versicolor
76 6.6 NA NA 1.4 versicolor
80 5.7 2.6 NA 1.0 versicolor
82 5.5 2.4 NA 1.0 versicolor
85 5.4 3.0 NA 1.5 versicolor
90 5.5 2.5 NA 1.3 versicolor
91 5.5 2.6 NA 1.2 versicolor
92 6.1 3.0 NA 1.4 versicolor
97 5.7 2.9 NA 1.3 versicolor
99 5.1 2.5 NA 1.1 versicolor
104 6.3 2.9 NA 1.8 virginica
107 NA 2.5 4.5 1.7 virginica
109 6.7 2.5 NA 1.8 virginica
113 6.8 3.0 NA 2.1 virginica
116 6.4 3.2 NA 2.3 virginica
121 NA 3.2 5.7 2.3 virginica
122 5.6 2.8 NA 2.0 virginica
123 7.7 2.8 NA 2.0 virginica
128 6.1 NA 4.9 1.8 virginica
131 7.4 NA 6.1 1.9 virginica
138 6.4 3.1 NA 1.8 virginica
139 6.0 3.0 NA 1.8 virginica
147 6.3 NA NA 1.9 virginica
Podríamos contar la cantidad de faltantes para una variable:
sum(is.na(iris$Pet.L))
[1] 27
O podríamos verificar la cantidad de instancias que poseen algún faltante:
sum(!complete.cases(iris))
[1] 37
También podemos analizar la proporción de faltantes sobre el total de instancias:
cat('Sep.L.:', mean(is.na(iris$Pet.L))*100, '% NA (faltantes)')
Sep.L.: 18 % NA (faltantes)
La librería VIM (Visualization and Imputation of Missing Values) tiene gran cantidad de recursos para el análisis e imputación de faltantes. A continuación verificamos combinaciones de faltantes por atributo:
library(VIM)
# Proporción de cada combinación
faltantes = summary(aggr(iris, sortVar=TRUE, plot=F))
print(faltantes$combinations)
Combinations Count Percent
1 0:0:0:0:0 113 75.3333333
2 0:0:0:1:0 1 0.6666667
3 0:0:1:0:0 25 16.6666667
4 0:1:0:0:0 7 4.6666667
5 0:1:1:0:0 2 1.3333333
6 1:0:0:0:0 2 1.3333333
A su vez, es posible graficar el análisis de faltantes:
aggr(iris, sortVar=TRUE, oma = c(16, 5, 5, 3), numbers=T)
Variables sorted by number of missings:
Variable Count
Pet.L. 0.180000000
Sep.W. 0.060000000
Sep.L. 0.013333333
Pet.W. 0.006666667
Species 0.000000000
Además, la librería MICE provee un gráfico que detalla la cantidad de atributos con missing por cada atributo:
library(mice) # Cargamos la librería
md.pattern(iris, rotate.names=FALSE)
Species Pet.W. Sep.L. Sep.W. Pet.L.
113 1 1 1 1 1 0
25 1 1 1 1 0 1
7 1 1 1 0 1 1
2 1 1 1 0 0 2
2 1 1 0 1 1 1
1 1 0 1 1 1 1
0 1 2 9 27 39