我在R中没有太多经验。我正在尝试编写一个Gibbs采样器,我有一个这样的for循环:
for (iNum in 1:totNum) {
rateNum <- Y3[iNum]
if(Y3[iNum] > 0) {
yStar3[iNum] <- rtnorm(1, mean = Mean3[iNum], sd = sqrt(Var3),
lower = gz[rateNum], upper = gz[rateNum + 1])
} else if(Y3[iNum] == 0) {
yStar3[iNum] <- rtnorm(1, mean = Mean3[iNum], sd = sqrt(Var3),
lower = -Inf, upper = Inf);
}
}
这花费了太多时间。我尝试使用lapply
,但这还不够快。有没有办法对这个循环进行矢量化?
谢谢你,最好的问候!!
答案 0 :(得分:2)
所以,似乎你没有迭代之间的依赖关系,这使得它非常简单地进行矢量化
lhs = rtnorm(length(Y3), mean = Mean3, sd = sqrt(Var3), lower = gz[Y3],
upper = gz[Y3 + 1])
rhs = rtnorm(length(Y3), mean=Mean3, sd = sqrt(Var3), lower=-Inf, upper=Inf)
ifelse(Y3 > 0, lhs, rhs)
这里的问题是rtnorm必须在其输入参数(mean,lower和upper)上进行矢量化。可能不是这种情况,在这种情况下,你将不得不做更多的工作。
答案 1 :(得分:2)
最简单的方法是生成条件的两半并选择您想要的那一半。 mean
参数将采用向量方式,因此您可以得到如下内容:
yStar3 <- ifelse(
Y3 > 0,
rtnorm(totNum, mean=Mean3, sd=sqrt(Var3), lower=gz[ratenum], upper=gz[rateNum+1]),
rtnorm(totNum, mean=Mean3, sd=sqrt(Var3), lower=-Inf, upper=Inf))
您必须优化ifelse
,可能还有一个附加条件,即Y3小于零的情况,但这是一般的想法。
更新:@hadley建议在rtnorm中移动ifelse:
yStar3 <- rtnorm(totNum, mean=Mean3, sd=sqrt(Var3),
lower=ifelse(Y3>0,gz[rateNum], -Inf),
upper=ifelse(Y3>0,gz[rateNum+1], Inf))
现在基本上没有不必要的计算。
更新:当然,正如评论者指出的那样,1是错误的;它应该是totNum。
答案 2 :(得分:1)
如果您的变量没有一些值,这是一个问题,但您想要做的事情是相当简单的。你想坚持使用所有的矢量化语句,尽量不要占用太多内存。这是基本策略:
第1步:弄清楚如何计算所有数字。
# The number of values you need from 'rtnorm'
sum(Y3 > 0)
sum(Y3 == 0)
# The means you need from the 'Mean3' array
Mean3[Y3 > 0]
Mean3[Y3 == 0]
# Lower and upper limits for Y3 > 0
gz[Y3[Y3 > 0]]
gz[Y3[Y3 > 0] + 1]
第2步:在yStar3的矢量过滤器上使用这些值。如果没有一些示例数据和变量值,我不能完全确定我的所有语法都是完美的,但它看起来应该是这样的:
yStar3[Y3 > 0] <- rtnorm(
sum(Y3 > 0),
mean = Mean3[Y3 > 0],
sd = sqrt(Var3),
lower = gz[Y3[Y3 > 0]],
upper = gz[Y3[Y3 > 0] + 1])
yStar3[Y3 == 0] <- rtnorm(
sum(Y3 == 0),
mean = Mean3[Y3 == 0],
sd = sqrt(Var3),
lower = -Inf,
upper = Inf)