Answers:
试试这个:
df <- df[,colSums(is.na(df))<nrow(df)]
到目前为止,提供的这两种方法在创建大数据集时(以及其他内存问题中)失败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]
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
data.frame
。这里没有什么真正需要的data.table
。关键是lapply
,可以避免使用复制整个对象is.na(df)
。指出+10。
bd1 <- bd[, unlist(lapply(bd, function(x), !all(is.na(x))))]
,
后function(x)
-顺便说一句感谢的例子
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
dplyr
解决方案。并不失望。谢谢!
另一种方法是使用该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()
用来查看哪些列满足您的条件,因此只需使用一种apply
方法,就可以简单地进行与Musa的答案相同的子集。
> !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
您可以使用看门人包 remove_empty
library(janitor)
df %>%
remove_empty(c("rows", "cols")) #select either row or cols or both
另外,另一种dplyr方法
library(dplyr)
df %>% select_if(~all(!is.na(.)))
要么
df %>% select_if(colSums(!is.na(.)) == nrow(df))
如果您只想排除/保留具有一定数量的缺失值的列,这也很有用,例如
df %>% select_if(colSums(!is.na(.))>500)