从所有值为NA的数据框中删除列
我遇到了一个数据框的问题,我自己也无法真正解决这个问题:
dataframe具有任意属性作为列 , 每行代表一个数据集 。
问题是:
如何摆脱所有行的值为NA的列 ?
尝试这个:
df <- df[,colSums(is.na(df))<nrow(df)]
到目前为止,提供的两种方法在大数据集中失败,因为它们创build的是(其他内存问题)是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
另一种方法是使用apply()
函数。
如果你有data.frame
df <- data.frame (var1 = c(1:7,NA), var2 = c(1,2,1,3,4,NA,NA,9), var3 = c(NA) )
那么你可以使用apply()
来查看哪些列满足你的条件,所以你可以简单地做与Musa的答案相同的子集,只需要一个apply
方法。
> !apply (is.na(df), 2, all) var1 var2 var3 TRUE TRUE FALSE > df[, !apply(is.na(df), 2, all)] var1 var2 1 1 1 2 2 2 3 3 1 4 4 3 5 5 4 6 6 NA 7 7 NA 8 NA 9
我希望这也可以帮助。 它可以做成一个单一的命令,但是我发现通过将它分成两个命令使我更容易阅读。 我用下面的说明做了一个function,并且快速地工作。
naColsRemoval = function (DataTable) { na.cols = DataTable [ , .( which ( apply ( is.na ( .SD ) , 2 , all ) ) )] DataTable [ , unlist (na.cols) := NULL , with = F] }
.SD将允许将validation限制在表的一部分,如果你愿意的话,但它会把整个表作为
df[sapply(df, function(x) all(is.na(x)))] <- NULL