从R中的表中识别并删除单值列

时间:2014-07-31 08:32:13

标签: r apply

我有一个相当大的数据集(约250k行和400个cols @ .5gb),其中许多列是单值的(即它们只有一个值)。要从数据集中删除这些列,我使用data[, apply(data, 2, function(x) length(unique(x)) != 1)],它可以正常工作。我想知道是否有更有效的方法可以做到这一点?这在我的电脑上需要:

> system.time(apply(data, 2, function(x) length(unique(x))))
#   user  system elapsed 
#  34.37    0.71   35.15 

对于一个数据集来说这不是很糟糕,但我想在不同的数据集上重复多次。

2 个答案:

答案 0 :(得分:1)

您可以改为使用lapply

data[, unlist(lapply(data, function(x) length(unique(x)) > 1L))]

请注意,我添加了unlist将结果列表转换为TRUE / FALSE值的向量,该值将用于子集化。

编辑:这是一个小基准:

library(benchmark)

a <- runif(1e4)
b <- 99
c <- sample(LETTERS, 1e4, TRUE)
df <- data.frame(a,b,c,a,b,c,a,b,c,a,b,c,a,b,c,a,b,c,a,b,c,a,b,c,a,b,c)

microbenchmark(
  apply = {df[, apply(df, 2, function(x) length(unique(x)) != 1)]},
  lapply = {df[, unlist(lapply(df, function(x) length(unique(x)) > 1L))]},
  unit = "relative",
  times = 100)

#Unit: relative
#  expr      min       lq   median       uq      max neval
#apply  41.29383 40.06719 39.72256 39.16569 28.54078   100
#lapply  1.00000  1.00000  1.00000  1.00000  1.00000   100

请注意,apply将首先将data.frame转换为矩阵,然后执行效率较低的操作。因此,在您使用data.frame的大多数情况下,您可以(并且应该)避免使用apply并使用例如而是lapply

答案 1 :(得分:1)

您也可以尝试:

set.seed(40)
df <- as.data.frame(matrix(sample(letters[1:3], 3*10,replace=TRUE), ncol=10))
Filter(function(x) (length(unique(x))>1), df)

或者

df[,colSums(df[-1,]==df[-nrow(df),])!=(nrow(df)-1)] #still better than `apply`

还包括速度比较(@ beginneR的样本数据)

 microbenchmark(
 new ={Filter(function(x) (length(unique(x))>1), df)},
 new1={df[,colSums(df[-1,]==df[-nrow(df),])!=(nrow(df)-1)]},
 apply = {df[, apply(df, 2, function(x) length(unique(x)) != 1)]},
 lapply = {df[, unlist(lapply(df, function(x) length(unique(x)) > 1L))]},
 unit = "relative", 
 times = 100)
 # Unit: relative
 #  expr        min         lq    median         uq      max neval
 #   new  1.0000000  1.0000000  1.000000  1.0000000 1.000000   100
 #  new1  4.3741503  4.5144133  4.063634  3.9591345 1.713178   100
 # apply 23.9635826 24.0895813 21.361140 20.7650416 5.757233   100
 #lapply  0.9991514  0.9979483  1.002005  0.9958308 1.002603   100