循环遍历列表并使用该列表中的元素

时间:2011-09-27 02:48:32

标签: r loops

在下面的代码中,我不是以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 
}

3 个答案:

答案 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次代表就不会清楚了。) plot of coverage

答案 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
相关问题