Eliminar columnas de un data.frame donde NA es más del 15% de la longitud de la columna

Tengo un data.frame de 10 columnas diferentes (la longitud de cada columna es la misma). Quiero eliminar cualquier columna que tenga ‘ NA ‘ mayor que el 15% de la longitud de la columna.

¿Es necesario primero hacer una función para calcular el porcentaje de NA para cada columna y luego hacer otro data.frame donde aplique la función? ¿Cuál es la mejor manera de hacer esto?

En primer lugar, siempre es bueno compartir algunos datos de muestra. No necesita ser su información real, algo inventado está bien.

 set.seed(1) x <- rnorm(1000) x[sample(1000, 150)] <- NA mydf <- data.frame(matrix(x, ncol = 10)) 

En segundo lugar, puede usar funciones incorporadas para obtener lo que necesita. Aquí, is.na(mydf) realiza una comprobación lógica y devuelve un data.frame de TRUE y FALSE . Como TRUE y FALSE equivalen a 1 y 0 , podemos usar colMeans para obtener la media del número de valores TRUE (es NA ). Eso, a su vez, se puede verificar de acuerdo con sus estipulaciones, en este caso, ¿qué columnas tienen más de 15% de valores de NA ?

 colMeans(is.na(mydf)) > .15 # X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 # TRUE TRUE FALSE FALSE FALSE TRUE FALSE TRUE TRUE FALSE 

Como podemos ver, deberíamos descartar X1, X2, X6, X8 y X9. De nuevo, aprovechando los vectores lógicos, así es cómo:

 > final <- mydf[, colMeans(is.na(mydf)) <= .15] > dim(final) [1] 100 5 > names(final) [1] "X3" "X4" "X5" "X7" "X10" 

Podrías hacerlo con data.table como tal

Cargar datos en data.table. Llámalo DT. Say cols 2 a 4 son numéricos.

 Theta = 0.15 Drop <- DT[, lapply(.SD, function (x) {sum(is.na(x))/length(x) > Theta} ), .SDcols = 2:4] Cols.2.Drop <- names(Drop)[which(Drop==TRUE)] DT[, (Cols.2.Drop) := NULL] 

Probado con datos aquí:

 Obs Var1 Var2 Var3 A0001 21 21 21 A0002 21 78 321 A0003 32 98 87 A0004 21 12 54 A0005 21 13 45 A0006 21 87 45 B0007 84 NA 45 B0008 21 NA 98 B0009 2 NA 45 B0010 12 NA 45