更快地从置换数据集生成大量矢量列表[R]

时间:2017-07-05 22:20:24

标签: r performance list permutation

设置出于模拟的目的,我生成了一个B=2000元素列表,每个元素都是排列过程的输出,我首先在其中置换200x8000矩阵的行和每列的 ,我计算第一行和第二行之间的Kolmogorov-Smirnov检验统计量(你可以想到第一行) 100行作为一组的数据,第二组100行作为另一组的数据。)

问题此过程需要很长时间(约30-40分钟)才能生成列表。有更快的方法吗?将来,我希望将B增加到更大的值。

代码

B=2000
n.row=200; n.col=8000
#Generate sample data
samp.dat = matrix(rnorm(n.row*n.col),nrow=n.row)

perm.KS.list = NULL
for (b in 1:B){
    #permute the rows
    perm.dat.tmp = samp.dat[sample(nrow(samp.dat)),]
    #Compute the permutation-based test statistics
    perm.KS.list[[b]]= apply(perm.dat.tmp,2,function(y) ks.test.stat(y[1:100],y[101:200]))
}


#Modified KS-test function (from base package)
ks.test.stat <- function(x,y){
  x <- x[!is.na(x)]
  n <- length(x)
  y <- y[!is.na(y)]
  n.x <- as.double(n)
  n.y <- length(y)
  w <- c(x, y)
  z <- cumsum(ifelse(order(w) <= n.x, 1/n.x, -1/n.y))
  z <- z[c(which(diff(sort(w)) != 0), n.x + n.y)] #exclude ties
  STATISTIC <- max(abs(z))
  return(STATISTIC)
}

1 个答案:

答案 0 :(得分:2)

1:B循环有几个要优化的地方,但我同意真正的消费者是内在功能。因为您正在模拟表现良好的自举样本,所以您可以做出两个简化的假设,即一般base函数不能:

  1. 没有遗漏的值。这样可以避免is.na()调整
  2. 双方(即x&amp; y)具有相同数量的元素,因此您无需单独计算它们。而不是在循环中拆分y,而是将它们连接回函数(进入w),只需将它保持在一起即可。平衡边也允许简化,例如删除ifelse()子句。它产生一堆0/1,通过整数运算重新调整为-1 / 1s。
  3. 该功能减少,可节省约25%的时间。我在cumsum()内添加了整数而不是双精度。

    ks.test.stat.balanced <- function(w){
      n     <- as.integer(length(w) * .5)
      # z   <- cumsum(ifelse(order(w) <= n, 1L, -1L)) / n
      z     <- cumsum((order(w) <= n)*2L - 1L) / n
      # z   <- z[c(which(diff(sort(w)) != 0), n + n)] #exclude ties
      return( max(abs(z)) )
    }
    

    你的高斯不应经常发生关系,diff(sort(.))非常昂贵。如果您愿意删除该保护,则时间减少约65%。

    如果您将z的等式移到abs(),它会为所有这些代表节省一点时间。我把它分开在上面,所以它更容易阅读。

    如果模拟不平衡,

    编辑我建议你:

    1. 仍然保留is.na
    2. 仍然通过w
    3. 仍然尽可能地保留在integer,而不是numeric,但
    4. 现在包含参数n1&amp;两个组大小n2
    5. 另外,在n之前尝试预先计算1 / cumsum()以避免大量昂贵的划分。尝试考虑其他数学方法从内循环中提取计算,以减少它的发生频率。