我已经创建了以下代码,它在R中的for循环中嵌套for循环。它是一个计算Power的模拟。我已经知道R对于做循环并不是很好,但我想知道是否有任何效率可以让我的运行速度更快一些。我对R以及任何类型的编程都很新。现在我看到的运行时间是:
m = 10我得到.17秒
m = 100我得到3.95秒
m = 1000我得到246.26秒
m = 2000我得到1003.55秒
我希望设定采样的次数,m,超过100K,但我甚至不敢将其设置为10K
以下是代码:
m = 1000 # number of times we are going to take samples
popmean=120 # set population mean at 120
popvar=225 # set known/established population
variance at 225
newvar=144 # variance of new methodology
alpha=.01 # set alpha
teststatvect = matrix(nrow=m,ncol=1) # empty vector to populate with test statistics
power = matrix(nrow=200,ncol=1) # empty vector to populate with power
system.time( # not needed - using to gauge how long this takes
for (n in 1:length(power)) # begin for loop for different sample sizes
for(i in 1:m){ # begin for loop to take "m" samples
y=rnorm(n,popmean,sqrt(newvar)) # sample of size n with mean 120 and var=144
ts=sum((y-popmean)^2/popvar) # calculate test statistic for each sample
teststatvect[i]=ts # loop and populate the vector to hold test statistics
vecpvals=pchisq(teststatvect,n) # calculate the pval of each statistic
power[n]=length(which(vecpvals<=alpha))/length(vecpvals) # loop to populate power vector. Power is the proportion lessthan ot equal to alpha
}
}
)
答案 0 :(得分:3)
我重新组织了你的代码并摆脱了内循环。
replicate
快得多,如另一个答案中所建议的那样,对于可读性很好,但在这种情况下你通过对块中的随机数进行采样可以做得更好)colSums
比在for
循环内汇总或使用apply
更快。mean(pvals<=alpha)
代替sum(pvals<=alpha)/length(alpha)
sapply
来调整大小向量的范围(不比for
循环快,但是更清洁,也许更容易概括)。代码:
powfun <- function(ssize=100,
m=1000, ## samples per trial
popmean=120, ## pop mean
popvar=225, ## known/established pop variance
newvar=144, ## variance of new methodology
alpha=0.01,
sampchisq=FALSE) ## sample directly from chi-squared distrib?
{
if (!sampchisq) {
ymat <- matrix(rnorm(ssize*m,popmean,sd=sqrt(newvar)),ncol=m)
ts <- colSums((ymat-popmean)^2/popvar) ## test statistic
} else {
ts <- rchisq(m,df=ssize)*newvar/popvar
}
pvals <- pchisq(ts,df=ssize) ## pval
mean(pvals<=alpha) ## power
}
你真的需要样本大小的每个整数值的功率,或者更宽的间距样本是否正常(如果你需要精确值,插值可能非常准确)
ssizevec <- seq(10,250,by=5)
set.seed(101)
system.time(powvec <- sapply(ssizevec,powfun,m=5000)) ## 13 secs elapsed
速度相当快,如果需要,可能会让你达到m=1e5
,但我不太清楚为什么你需要那些精确的结果 - 功率曲线相当平滑{{1} } ...
如果您不耐烦地等待长时间的模拟,您还可以通过将m=5000
替换为sapply(ssizevec,powfun,m=5000)
来获取打印进度条
最后,我认为你可以通过直接采样卡方值或通过分析功率计算(!)来加快整体速度。我认为library(plyr); aaply(ssizevec,.margins=1,powfun,.progress="text",m=5000)
相当于循环的前两行,你甚至可以直接对卡方密度进行数值计算......
rchisq(m,df=ssize)*newvar/popvar
(我刚试过这个,在样本大小的每个值上从1到200抽样system.time(powvec2 <- sapply(ssizevec,powfun,m=5000,sampchisq=TRUE))
## 0.24 seconds elapsed
......需要24秒......但我仍然认为这可能是不必要的。)
图片:
m=1e5
答案 1 :(得分:0)
一般而言,您希望尽可能利用矢量化,而不是速度与可读性/理解力。
为什么在内部循环中写入power[n]
(我想也计算vecpals
)?内循环执行后,不应该在外循环中吗?您可能希望在两个循环外部移动平方根的计算。
为什么teststatvect
和power
被初始化为矩阵(明确是二维数组)而不是向量(或者更确切地说,作为一维数组,使用array
)? variance at 225
只是上一行评论的结尾吗?您可能想要检查格式。 (这是家庭作业吗?)
对于你在这里尝试做的事情,你可能想要利用非常方便的函数replicate
,也许通过编写一个特定的函数来调用它。