设置出于模拟的目的,我生成了一个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)
}
答案 0 :(得分:2)
1:B
循环有几个要优化的地方,但我同意真正的消费者是内在功能。因为您正在模拟表现良好的自举样本,所以您可以做出两个简化的假设,即一般base
函数不能:
is.na()
调整x
&amp; y
)具有相同数量的元素,因此您无需单独计算它们。而不是在循环中拆分y
,而是将它们连接回函数(进入w
),只需将它保持在一起即可。平衡边也允许简化,例如删除ifelse()
子句。它产生一堆0/1,通过整数运算重新调整为-1 / 1s。该功能减少,可节省约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()
,它会为所有这些代表节省一点时间。我把它分开在上面,所以它更容易阅读。
编辑我建议你:
is.na
,w
,integer
,而不是numeric
,但n1
&amp;两个组大小n2
。 另外,在n
之前尝试预先计算1 / cumsum()
以避免大量昂贵的划分。尝试考虑其他数学方法从内循环中提取计算,以减少它的发生频率。