Показывать столбцы с NA в файле data.frame

Я хотел бы показать имена столбцов в большом фреймворке данных, которые содержат отсутствующие значения. В принципе, я хочу эквивалент complete.cases(df), но для столбцов, а не строк. Некоторые столбцы не являются числовыми, поэтому что-то вроде

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

возвращает "Ошибка в colMeans (df):" x "должно быть числовым". Итак, мое текущее решение состоит в том, чтобы перенести данные и запустить complete.cases, но я предполагаю, что какой-то вариант применения (или что-то в plyr) намного эффективнее.

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"

Может ли кто-нибудь показать мне более эффективную функцию для определения столбцов с NA?

Ответ 1

Это самый быстрый способ, которым я знаю:

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

EDIT:

Я предполагаю, что все остальные записали его полностью, поэтому здесь оно завершено:

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

И если вы microbenchmark 4 решения на машине 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

И вот визуальное представление: enter image description here

Изменить В то время, когда я писал, это anyNA не существовало, или я не знал об этом. Это может ускорить процесс... в справочном руководстве для ?anyNA:

Общая функция anyNA реализует any(is.na(x)) возможно более быстрым способом (особенно для атомных векторов).

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

Ответ 2

Один из способов...

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

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

Объяснение: поскольку результат y является логическим вектором, names(y[y]) возвращает имена y только для тех случаев, когда y имеет значение TRUE.

Ответ 3

Вот один из способов:

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

Надеюсь, что это поможет,

Маноэл