【问题标题】:Loop returning more values than expected and NA's循环返回比预期和 NA 更多的值
【发布时间】:2019-09-19 02:12:58
【问题描述】:

我正在尝试模拟一些数据以估计样本量,但我的循环返回了意外的结果。

我正在尝试从具有不同数量的样本大小的生成值向量中对 a 进行采样,然后将平均值和标准差连接起来以进行多次模拟。

library(MCMCglmm)
library(tidyverse)

Est <- function(n, mean, sd, lower, upper, samp_min, samp_max, samp_int, nsim){

        Data <- round(rtnorm(n, mean, sd, lower, upper), digits = 0) # Create a vector to sample from

        Samp_size <- seq(samp_min, samp_max, samp_int) # Create vector of sample sizes

        # Set up enpty results data frames
        Results_samp <- data.frame()
        Results <- data.frame()

        for(i in 1:nsim){ ## Loop through number of simulations

        for (j in seq_along(Samp_size)) { # Loop through sample sizes
                Score <- sample(Data, j, replace = TRUE)
                Nsubj <- Samp_size[j]
                Mean <- mean(Score, na.rm = TRUE)
                SD <- sd(Score, na.rm = TRUE)
                Results_samp <- rbind(Results_samp, 
                                      data.frame(
                                              Nsubj,
                                              Mean,
                                              SD))
        }
        Results <- rbind(Results, Results_samp)   
        }

        Results
}

Test <- Est(n = 1000, mean = 55, sd = 37, lower = 0, upper = 100, 
            samp_min = 5, samp_max = 20, samp_int = 5, nsim = 5)

这将创建一个包含 60 行的数据框,我预计其中有 20 行(4 个样本大小的 5 次模拟),并且对于 5 的样本大小,我总是返回 NA。

谁能看出我哪里出错了?

谢谢!

【问题讨论】:

  • 您需要在您的内部 for 循环中“重置”Results_samp。我在下面给出了一个例子。

标签: r simulation


【解决方案1】:

通常,使用rbind 动态增长data.frame 是一种非常在 R 中做事效率低下的方法。几乎总是有更好/更快的方法来做你想做的事.

除此之外,在回答您的问题方面,让我们看一下嵌套for 循环的简化版本

x1 <- data.frame()
x2 <- data.frame()
for (i in 1:5) {
    for (j in 1:4) x1 <- rbind(x1, data.frame(x1 = i, x2 = i^2))
    x2 <- rbind(x2, x1)
}

看看x2有60行吗?

原因是您从未重置x1。如果我们解决这个问题

x1 <- data.frame()
x2 <- data.frame()
for (i in 1:5) {
    for (j in 1:4) x1 <- rbind(x1, data.frame(x1 = i, x2 = i^2))
    x2 <- rbind(x2, x1)
    x1 <- data.frame()
}

正如预期的那样,我们有nrow(x2) = 20

【讨论】:

  • 谢谢!知道为什么 sd 总是样本大小为 5 的 NA 吗?你能推荐一个替代 rbind 的方法吗?
  • @JLC SD 将是 NA 如果您只有一个条目,这将在您的内部 j 循环的第一步中发生。你确定这个代码位是正确的:Score &lt;- sample(Data, j, replace = TRUE)?您正在采样j 样本,取值1:4;也许你的意思是sample(Data, Samp_size[j], replace = T)
  • 至于优化代码:如果必须使用循环,使用嵌套lapply(这是伪装的for循环),返回嵌套list;然后rbind 一次(而不是在循环的每一步)。更好的是,使用矢量化操作(这将取决于函数)。
  • 谢谢!!我确实打算拥有sample(Data, Samp_size[j], replace = T)!也感谢矢量化建议;我会看看我是否可以转换这个功能。由于需要大量复制,这需要很长时间。
  • @JLC 不客气。您可能要考虑的另一件事是将您的代码发布到Code Review。由于您有一段工作且可重现的代码,您可能想在那里询问可能的代码优化。他们也有一个 R 代码标签:-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-01-06
  • 2019-03-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-31
相关资源
最近更新 更多