Два подхода, предложенных до сих пор, терпят неудачу с большими наборами данных, поскольку (среди прочих проблем с памятью) они создают is.na(df)
, который будет объектом того же размера, что и df
.
Вот два подхода, которые более эффективны при использовании памяти и времени
Подход с использованием Filter
Filter(function(x)!all(is.na(x)), df)
и подход с использованием data.table (для общего времени и эффективности использования памяти)
library(data.table)
DT <- as.data.table(df)
DT[,which(unlist(lapply(DT, function(x)!all(is.na(x))))),with=F]
примеры использования больших данных (30 столбцов, 1e6 строк)
big_data <- replicate(10, data.frame(rep(NA, 1e6), sample(c(1:8,NA),1e6,T), sample(250,1e6,T)),simplify=F)
bd <- do.call(data.frame,big_data)
names(bd) <- paste0('X',seq_len(30))
DT <- as.data.table(bd)
system.time({df1 <- bd[,colSums(is.na(bd) < nrow(bd))]})
# error -- can't allocate vector of size ...
system.time({df2 <- bd[, !apply(is.na(bd), 2, all)]})
# error -- can't allocate vector of size ...
system.time({df3 <- Filter(function(x)!all(is.na(x)), bd)})
## user system elapsed
## 0.26 0.03 0.29
system.time({DT1 <- DT[,which(unlist(lapply(DT, function(x)!all(is.na(x))))),with=F]})
## user system elapsed
## 0.14 0.03 0.18