从R中的大data.frame中删除满足条件的列

时间:2017-03-30 10:37:41

标签: r time

我有一个很大的数据框架; 100,000个变量的100,000次观测。

在所有观察中,大多数变量实际上都是0,我想删除那些变量/列。

我尝试了以下内容,

data <- data[apply(data, 2, function(x){all(x == 0)})]

但申请需要花费大量时间来解决。

我尝试了while,以防问题同时适用于所有data

i <- 1
while (i <= ncol(data)) {
  if (all(data[i] == 0)) {
    data[i] <- NULL
  } else {
    i <- i+1
  }
}

但是我一直遇到同样的问题,花了很多时间。

所以,

  • 为什么这项操作需要很长时间?即使data.frame很大,操作也很简单。

,最重要的是

  • 有没有办法更快地完成这项工作?

2 个答案:

答案 0 :(得分:1)

你的问题令人困惑。我假设您要删除变量,即列。您可以使用any自动强制值来键入logical。关于comparison of floating point numbers的常见警告适用。如果你想安全地玩它,你需要测试双精度是否小于某个精度值,这个速度会慢一些,但是正确地说它是正确的。

DF <- data.frame(x = 1:3, y = 1:3/10, z = 0)
DF[] <- lapply(DF, function(x) if (any(x)) x else NULL)
#Warning messages:
#1: In any(x) : coercing argument of type 'double' to logical
#2: In any(x) : coercing argument of type 'double' to logical
#  x   y
#1 1 0.1
#2 2 0.2
#3 3 0.3

set.seed(42)
DF2 <- as.data.frame(matrix(sample(0:1, 700*1e5, TRUE, prob = c(0.999999, 0.000001)), ncol = 700))

system.time(DF2[] <- lapply(DF2, function(x) if (any(x)) x else NULL))
#user  system elapsed 
#0.10    0.02    0.11 

更安全的选项:

set.seed(42)
DF2 <- as.data.frame(matrix(sample(0:1, 700*1e5, TRUE, prob = c(0.999999, 0.000001)), ncol = 700))

system.time(DF2[] <- lapply(DF2, function(x) if (any(x > 1e-16)) x else NULL))
#user  system elapsed 
#0.34    0.11    0.45 

答案 1 :(得分:1)

使用像colSums这样的矢量化操作可加快我机器上的操作 -

> set.seed(123)
> df = data.frame(matrix(sample(0:1,100000*700,replace = T,prob = c(0.9999999,0.0000001)), ncol = 700))
> system.time(df1 <- df[apply(df, 2, function(x){all(x == 0)})])
user  system elapsed 
1.386   0.821   2.225 
> system.time(df2 <- df[,which(colSums(df)==0)])
user  system elapsed 
0.243   0.082   0.326 
> identical(df1, df2)
[1] TRUE