Удалить столбцы из фрейма данных, где все значения NA
У меня возникли проблемы с фрейм данных, и я не мог решить эту проблему сам:
Элемент dataframe имеет произвольную свойства в виде столбцов и каждую строку - один набор данных.
Вопрос в том:
Как это избавиться от Столбцов, где к все строки значение NA?
6 ответов:
два подхода, предлагаемые до сих пор терпят неудачу с большими наборами данных, поскольку (среди других проблем с памятью) они создают
is.na(df), который будет объект того же размера, что иdf.вот два подхода, которые являются более эффективной памяти и времени
подход с использованием
FilterFilter(function(x)!all(is.na(x)), df)и подход с использованием данных.таблица (для общего времени и эффективности памяти)
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
dplyrтеперьselect_ifглагол, который может быть полезным здесь:library(dplyr) temp <- data.frame(x = 1:5, y = c(1,2,NA,4, 5), z = rep(NA, 5)) not_all_na <- function(x) any(!is.na(x)) not_any_na <- function(x) all(!is.na(x)) > temp x y z 1 1 1 NA 2 2 2 NA 3 3 NA NA 4 4 4 NA 5 5 5 NA > temp %>% select_if(not_all_na) x y 1 1 1 2 2 2 3 3 NA 4 4 4 5 5 5 > temp %>% select_if(not_any_na) x 1 1 2 2 3 3 4 4 5 5
Я надеюсь, что это также может помочь. Это можно было бы сделать в одну команду, но мне было легче читать, разделив его на две команды. Я сделал функцию со следующей инструкцией и работал молниеносно.
naColsRemoval = function (DataTable) { na.cols = DataTable [ , .( which ( apply ( is.na ( .SD ) , 2 , all ) ) )] DataTable [ , unlist (na.cols) := NULL , with = F] }. SD позволит ограничить проверку частью таблицы, если вы хотите, но он будет принимать всю таблицу как
Comments