加快改变群体的速度

时间:2015-09-30 05:23:23

标签: r loops vectorization tapply

我正在编写一个函数来计算两组平均值的差异,但组实际上每次都会改变,得到结果很简单,但问题是我有一个相当大的数据集,所以速度是键。这是"可读"版本,以Iris数据为例。

loopDif = function(Nsim) {
  change = numeric(Nsim)
  var = iris$Sepal.Length
  for (i in 1:Nsim){
    randomSpecies = sample(c("A","B"), length(var), replace=TRUE)
    change[i]  =  diff(tapply(var,  randomSpecies,  mean))
  }
  return(change)
}

> system.time(loopDif(10000))
   user  system elapsed 
   2.06    0.00    2.06 

我试图将代码矢量化:

slowDif <- function(Nsim) {
  change = numeric(Nsim)
  randomSpecies = replicate(Nsim,sample(c("A","B"), length(var), replace=TRUE))
  var = iris$Sepal.Length
  change = diff(unlist(lapply(split(randomSpecies, col(randomSpecies)), 
                             function(x) unlist(lapply(split(var, x), mean)))))
  return(change)
}

> system.time(slowDif(10000))
   user  system elapsed 
   1.42    0.00    1.42

现在速度更快,但仍然不够快,我希望不到1秒,甚至0.75秒。我如此着迷时间的原因是因为我有一个截止日期,但我目前的代码还不够快。

我也尝试过分析,告诉我unlist(lapply())部分是瓶颈,但我不知道如何重写它。

我真的很感激,如果有人能为我提供替代方案,甚至只是建议。感谢。

1 个答案:

答案 0 :(得分:1)

试试这个:

loopDif2 <- function(Nsim) {
    change <- numeric(Nsim)
    var <- iris$Sepal.Length
    nAgroup<-rbinom(Nsim,length(var),0.5)
    tot<-sum(var)
    for (i in 1:Nsim){
      change[i]<-sum(var[sample(length(var),nAgroup[i])])
    }
    change/nAgroup-(tot-change)/(length(var)-nAgroup)
}

单词:我首先提取A组的元素数量,隐含B组。然后我在每次迭代中提取A组的索引。我评估总和并除以元素的数量以得到平均值。另一个总和显然是变量的总和减去A组的总和。然后评估B组的平均值。

我的电脑上的表现:

system.time(loopDif(10000))
# user  system elapsed 
#3.855   0.004   3.867 
system.time(loopDif2(10000))
# user  system elapsed 
#0.139   0.000   0.139