从数据框中删除所有值为NA的列

时间:2010-04-15 08:59:53

标签: r apply dataframe

我遇到数据框架问题而无法自己解决这个问题:
数据框具有任意属性作为列每行代表一个数据集

问题是:
如何摆脱 ALL 行的值为NA的列

13 个答案:

答案 0 :(得分:125)

试试这个:

df <- df[,colSums(is.na(df))<nrow(df)]

答案 1 :(得分:79)

迄今为止提供的两种方法都失败了大数据集,因为(在其他内存问题中)他们创建了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 

答案 2 :(得分:24)

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

答案 3 :(得分:14)

另一种方法是使用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

答案 4 :(得分:5)

df[sapply(df, function(x) all(is.na(x)))] <- NULL

答案 5 :(得分:3)

带有purrr软件包的另一个选项:

library(dplyr)

df <- data.frame(a = NA,
                 b = seq(1:5), 
                 c = c(rep(1, 4), NA))

df %>% purrr::discard(~all(is.na(.)))
df %>% purrr::keep(~!all(is.na(.)))

答案 6 :(得分:2)

接受的答案不适用于非数字列。在this answer中,以下内容适用于包含不同数据类型的列

Filter(function(x) !all(is.na(x)), df)

答案 7 :(得分:2)

您可以使用看门人软件包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(.)))

OR

df %>% select_if(colSums(!is.na(.)) == nrow(df))

如果您只想排除/保留具有一定数量的缺失值的列,这也很有用。

 df %>% select_if(colSums(!is.na(.))>500)

答案 8 :(得分:1)

我希望这也可能有所帮助。它可以被制作成一个命令,但我发现通过将它分成两个命令来更容易阅读。我按照以下说明制作了一个功能,并且快速闪电。

naColsRemoval = function (DataTable) { na.cols = DataTable [ , .( which ( apply ( is.na ( .SD ) , 2 , all ) ) )] DataTable [ , unlist (na.cols) := NULL , with = F] }

如果您愿意,

.SD将允许将验证限制在表格的一部分,但它将整个表格视为

答案 9 :(得分:1)

仅适用于游戏,但您也可以使用janitor软件包。此功能将删除所有不适用的列,并且可以更改为也删除所有不适用的行。

df <- janitor::remove_empty(df, which = "cols")

答案 10 :(得分:1)

方便的base R选项可以是colMeans()

df[, colMeans(is.na(df)) != 1]

答案 11 :(得分:1)

根据我在应用先前答案时遇到的困难,我发现我需要修改他们的方法才能解决这里的问题:

如何清除所有行的值为NA的列?

首先请注意,只有当您没有重复的列时,我的解决方案才有效(此问题已由here (on stack overflow)

处理

第二,它使用dplyr

代替

df <- df %>% select_if(~all(!is.na(.)))

我发现有效的方法是

df <- df %>% select_if(~!all(is.na(.)))

重点是“不是”符号“!”需要在通用量词的外面。即select_if运算符作用于列。在这种情况下,它只会选择满足条件的那些

每个元素都等于“ NA”

答案 12 :(得分:0)

janitor :: remove_constant()很好地做到了这一点。