2012-05-13 26 views
17

Me gustaría mostrar los nombres de las columnas en un marco de datos grande que contenga valores faltantes. Básicamente, quiero el equivalente de complete.cases (df) pero para columnas, no filas. Algunas de las columnas son no numérico, así que algo comoMostrar columnas con NA en un data.frame

names(df[is.na(colMeans(df))]) 

devuelve "error en colMeans (df): 'x' debe ser numérico." Entonces, mi solución actual es transponer el dataframe y ejecutar complete.cases, pero supongo que hay alguna variante de apply (o algo en plyr) que sea mucho más eficiente.

nacols <- function(df) { 
    names(df[,!complete.cases(t(df))]) 
} 

w <- c("hello","goodbye","stuff") 
x <- c(1,2,3) 
y <- c(1,NA,0) 
z <- c(1,0, NA) 
tmp <- data.frame(w,x,y,z) 

nacols(tmp) 
[1] "y" "z" 

¿Alguien me puede mostrar una función más eficiente para identificar las columnas que tienen NA?

Respuesta

24

Esta es la manera más rápida que yo sepa:

unlist(lapply(df, function(x) any(is.na(x)))) 

EDIT:

supongo que todos los demás lo escribió completa así que aquí está completa:

nacols <- function(df) { 
    colnames(df)[unlist(lapply(df, function(x) any(is.na(x))))] 
} 

Y si microbenchmark las 4 soluciones en una máquina WIN 7:

Unit: microseconds 
    expr  min  lq median  uq  max 
1 ANDRIE 85.380 91.911 106.375 116.639 863.124 
2 MANOEL 87.712 93.778 105.908 118.971 8426.886 
3 MOIRA 764.215 798.273 817.402 876.188 143039.632 
4 TYLER 51.321 57.853 62.518 72.316 1365.136 

Y aquí es una representación visual de que: enter image description here

Editar En el momento de escribir este anyNA no existe o que no estaba al tanto de ello. Esto puede acelerar las cosas Moreso ... según el manual de ayuda para ?anyNA:

La función genérica anyNA implementa any(is.na(x)) de un modo más rápido posible (sobre todo para los vectores atómicas).

nacols <- function(df) { 
    colnames(df)[unlist(lapply(df, function(x) anyNA(x)))] 
} 
+0

Eso funciona perfectamente, gracias, especialmente para los puntos de referencia! – Moira

+2

+1 buena respuesta ... – Andrie

5

Aquí es una manera:

colnames(tmp)[colSums(is.na(tmp)) > 0] 

creo que sirve,

Manoel

6

Una forma ...

nacols <- function(x){ 
    y <- sapply(x, function(xx)any(is.na(xx))) 
    names(y[y]) 
} 

nacols(tmp) 
[1] "y" "z" 

Explicación: dado que el resultado y es un vector lógico, names(y[y]) devuelve los nombres de y solo para aquellos casos en que y es TRUE.

+0

Me interesaría saber el motivo del voto en negativo ... – Andrie

+0

Andrie, fui yo. Quise votar por todos los que dieron una respuesta correcta, pero en mi prisa fue un voto negativo. Me di cuenta más tarde cuando vi que tenías un 0 en lugar de un 2, pero mi voto estaba bloqueado. La única forma de solucionarlo (creo) es que si editas tu respuesta puedo cambiar el voto. –

+0

@TylerRinker Ah, de acuerdo. Todo está perdonado. He hecho una edición menor ... – Andrie

Cuestiones relacionadas