我想模拟exp(1)发行版中的一些数据,但它们必须是> 0.5。所以我使用了一个while循环,但它似乎没有像我想的那样工作。提前感谢您的回复!
x1<-c()
w<-rexp(1)
while (length(x1) < 100) {
if (w > 0.5) {
x1<- w }
else {
w<-rexp(1)
}
}
答案 0 :(得分:3)
1)问题中的代码存在以下问题:
我们在每次迭代时都需要一个新的随机变量,但如果if
条件为FALSE则只生成新的随机变量
x1
被反复覆盖而不是扩展
虽然可以使用while
repeat
似乎更好,因为最后的测试比开头的测试更合适
我们可以这样解决这个问题:
x1 <- c()
repeat {
w <- rexp(1)
if (w > 0.5) {
x1 <- c(x1, w)
if (length(x1) == 100) break
}
}
1a)以下是一种变化。请注意,如果没有if
分支,则条件为FALSE的else
计算结果为NULL,因此如果条件在标记为##的行上为FALSE,则不会将任何内容连接到x1
。
x1 <- c()
repeat {
w <- rexp(1)
x1 <- c(x1, if (w > 0.5) w) ##
if (length(x1) == 100) break
}
2)或者,这会产生200个指数随机变量,只保留大于0.5的变量。如果生成的数量少于100,则重复。最后,它从最后一批生成的前100个开始。我们选择200足够大,在大多数运行中只需要循环的一次迭代。
repeat {
r <- rexp(200)
r <- r[r > 0.5]
if (length(r) >= 100) break
}
r <- head(r, 100)
替代方案(2)实际上比(1)或(1a)更快,因为它的矢量化程度更高。尽管它丢失了比其他解决方案更多的指数随机变量。
答案 1 :(得分:2)
我建议反对while
(或任何其他接受/拒绝)循环;而是使用truncdist
中的方法:
# Sample 1000 observations from a truncated exponential
library(truncdist);
x <- rtrunc(1000, spec = "exp", a = 0.5);
# Plot
library(ggplot2);
ggplot(data.frame(x = x), aes(x)) + geom_histogram(bins = 50) + xlim(0, 10);
使用逆变换采样从截断的指数分布中抽取样本以避免在循环中拒绝样本,实现采样器也相当简单。这将是一种比任何基于接受/拒绝的采样方法更有效的方法,并且在您的情况下特别有效,因为存在截断形式的截断指数cdf。 有关详细信息,请参阅示例this post。