在下面的代码中,我不是以p = 0.01开始然后递增它,而是希望能够执行类似p =(1:99)/ 100的操作,然后循环执行p。例如,代替p = 0.01,让我们让p =(1:99)/ 100。现在,我尝试用p替换我的for循环中的1:99。但是,当我运行代码时,我开始遇到coverage [i]的问题(它返回数字(0))。看起来这应该是相当微不足道的,所以我希望我只是在我的代码中忽略了一些东西。
此外,如果您看到任何效率提升,请随时加入!谢谢=)
w=seq(.01,.99,by=.01)
coverage=seq(1:99)
p=0.01
for (i in 1:99){
count = 0
for (j in 1:1000){
x = rbinom(30,1,p)
se=sqrt(sum(x)/30*(1-sum(x)/30)/30)
if( sum(x)/30-1.644854*se < p && p < sum(x)/30+1.644854*se )
count = count + 1
}
coverage[i]=count/1000
print(coverage[i])
p=p+0.01
}
答案 0 :(得分:7)
我会处理中间部分而不是外部循环。
coverage <- p <- 1:99/100
z <- qnorm(0.95)
for (i in seq(along=p) ){
# simulate all of the binomials/30 at once
x <- rbinom(1000, 30, p[i])/30
# ses
se <- sqrt(x * (1-x)/30)
# lower and upper limits
lo <- x - z*se
hi <- x + z*se
# coverage
coverage[i] <- mean(p[i] > lo & p[i] < hi)
}
这对我来说几乎是即时的。诀窍是矢量化那些模拟和计算。在我6岁的Mac Pro上,增加到100,000个模拟重复只用了4秒钟。
(你需要增加重复数以查看结果中的结构; {100}代表的plot(p, coverage, las=1)
给出以下内容;仅用1000次代表就不会清楚了。)
答案 1 :(得分:2)
要回答原始问题,设置i in p
p
为0.01,0.02等,意味着coverage[i]
正在尝试coverage[0.01]
;由于[]
需要一个整数,因此将其截断为零,从而产生长度为零的数字numeric(0)
。
其他一个解决方案更好,但作为参考,使用原始循环来做,你可能想要像
这样的东西p <- seq(.01, .99, by=.01)
coverage <- numeric(length(p))
N <- 1000
n <- 30
k <- qnorm(1-0.1/2)
for (i in seq_along(p)) {
count <- 0
for (j in 1:N) {
x <- rbinom(n, 1, p[i])
phat <- mean(x)
se <- sqrt(phat * (1 - phat) / n)
if( phat-k*se < p[i] && p[i] < phat+k*se ) {
count <- count + 1
}
}
coverage[i] <- count/N
}
coverage
答案 2 :(得分:1)
@Karl Broman有一个很好的解决方案,真正展示了矢量化如何发挥作用。它仍然可以略微改善(约30%):
我更喜欢使用vapply
- 虽然它的速度提升在这里并不明显,因为循环只有99次。
f <- function(n=1000) {
z <- qnorm(0.95)/sqrt(30)
vapply(1:99/100, function(p) {
# simulate all of the binomials/30 at once
x <- rbinom(n, 30, p)/30
zse <- z*sqrt(x * (1-x))
# coverage
mean(x - zse < p & p < x + zse)
}, numeric(1))
}
system.time( x <- f(50000) ) # 1.17 seconds
这是使用vapply
的OP原始代码的一个版本,它比原始版本快20% - 但当然仍然比完全矢量化的解决方案慢......
g <- function(n=1000) {
vapply(seq(.01,.99,by=.01), function(p) {
count = 0L
for (j in seq_len(n)) {
x <- sum(rbinom(30,1,p))/30
# the constant is qnorm(0.95)/sqrt(30)
zse <- 0.30030781175850279*sqrt(x*(1-x))
if( x-zse < p && p < x+zse )
count = count + 1L
}
count/n
}, numeric(1))
}
system.time( x <- g(1000) ) # 1.04 seconds