如何正确地将与具有随机效应的变量名称关联的公式传递到“R”中的拟合回归模型中?
How to correctly pass formulas associated with a variable name with random effects into fitted regression models in `R`?
我目前遇到一个问题,我必须在将它们发送到回归函数之前预先指定我的公式。比如在R
中使用stan_gamm4
函数,我们有下面的例子:
dat <- mgcv::gamSim(1, n = 400, scale = 2) ## simulate 4 term additive truth
## Now add 20 level random effect `fac'...
dat$fac <- fac <- as.factor(sample(1:20, 400, replace = TRUE))
dat$y <- dat$y + model.matrix(~ fac - 1) %*% rnorm(20) * .5
br <- stan_gamm4(y ~ s(x0) + x1 + s(x2), data = dat, random = ~ (1 | fac),
chains = 1, iter = 200) # for example speed
现在,因为公式和随机公式是明确指定的,那么如果我们调用:
br$call$random
> ~(1 | fac)
我们能够检索随机效应的形式。
现在,让我们保持一切不变,但对随机部分使用一个表达式:
formula.rand <- as.formula( '~(1|fac)' )
那么,如果我们之前做了同样的事情,但是用 formula.rand
代替,我们有:
br <- stan_gamm4(y ~ s(x0) + x1 + s(x2), data = dat, random = formula.rand,
chains = 1, iter = 200) # for example speed
但是现在:我们有:
br$call$random
> formula.rand
代替原来的。许多贝叶斯包都依赖于访问 br$call$random
,那么有没有一种方法可以将变量用于公式,让它传入,并在调用 br$call$random
时保留原始关系?谢谢。
如果我理解正确,你的问题不是,stan_gamm4 可能计算了错误的结果(根据我的收集,情况并非如此),而只是 br$call$random
指的是变量名而不是公式。这似乎对模型的进一步 post 处理有问题。
由于 stan_gamm4
在内部使用 match.call
来查找调用,我不知道如何指定不同的模型以获得 "correct" br$call$random
正面。但您可以在事后通过以下方式简单地修改它:
br <- stan_gamm4(y ~ s(x0) + x1 + s(x2), data = dat, random = formula.rand)
br$call$random <- formula.rand
br$call$random
#> ~(1 | fac)
然后继续你正在做的事情。
恕我直言,这不是 stan_gamm4
的问题。在您的第二个示例中,如果您执行
class(br$call$random)
您会看到它属于 class "name"
。所以,好像 $call
只是一些包含内容的列表。为了以编程方式访问它,您需要使用
对其进行评估
eval(br$call$random)
为了得到~(1 | fac)
,也就是class"formula"
.
虽然我没有使用过 Stan,但这是 R 处理存储调用的方式中固有的问题。你可以看到它发生在 lm
,例如:
model <- function(formula)
{
lm(formula, data=mtcars)
}
m <- model(mpg ~ disp)
m$call$formula
# formula
最简单的解决方案是使用 substitute
构造调用以插入您要保留的实际值,而不是符号名称。在 lm
的情况下,这将类似于
model2 <- function(formula)
{
call <- substitute(lm(formula=.f, data=mtcars), list(.f=formula))
eval(call)
}
m2 <- model2(mpg ~ disp)
m2$call$formula
# mpg ~ disp
对于 Stan,你可以做到
stan_call <- substitute(br <- stan_gamm4(y ~ s(x0) + x1 + s(x2), data=dat, random=.rf,
chains=1, iter=200),
list(.rf=formula.rand))
br <- eval(stan_call)
我目前遇到一个问题,我必须在将它们发送到回归函数之前预先指定我的公式。比如在R
中使用stan_gamm4
函数,我们有下面的例子:
dat <- mgcv::gamSim(1, n = 400, scale = 2) ## simulate 4 term additive truth
## Now add 20 level random effect `fac'...
dat$fac <- fac <- as.factor(sample(1:20, 400, replace = TRUE))
dat$y <- dat$y + model.matrix(~ fac - 1) %*% rnorm(20) * .5
br <- stan_gamm4(y ~ s(x0) + x1 + s(x2), data = dat, random = ~ (1 | fac),
chains = 1, iter = 200) # for example speed
现在,因为公式和随机公式是明确指定的,那么如果我们调用:
br$call$random
> ~(1 | fac)
我们能够检索随机效应的形式。
现在,让我们保持一切不变,但对随机部分使用一个表达式:
formula.rand <- as.formula( '~(1|fac)' )
那么,如果我们之前做了同样的事情,但是用 formula.rand
代替,我们有:
br <- stan_gamm4(y ~ s(x0) + x1 + s(x2), data = dat, random = formula.rand,
chains = 1, iter = 200) # for example speed
但是现在:我们有:
br$call$random
> formula.rand
代替原来的。许多贝叶斯包都依赖于访问 br$call$random
,那么有没有一种方法可以将变量用于公式,让它传入,并在调用 br$call$random
时保留原始关系?谢谢。
如果我理解正确,你的问题不是,stan_gamm4 可能计算了错误的结果(根据我的收集,情况并非如此),而只是 br$call$random
指的是变量名而不是公式。这似乎对模型的进一步 post 处理有问题。
由于 stan_gamm4
在内部使用 match.call
来查找调用,我不知道如何指定不同的模型以获得 "correct" br$call$random
正面。但您可以在事后通过以下方式简单地修改它:
br <- stan_gamm4(y ~ s(x0) + x1 + s(x2), data = dat, random = formula.rand)
br$call$random <- formula.rand
br$call$random
#> ~(1 | fac)
然后继续你正在做的事情。
恕我直言,这不是 stan_gamm4
的问题。在您的第二个示例中,如果您执行
class(br$call$random)
您会看到它属于 class "name"
。所以,好像 $call
只是一些包含内容的列表。为了以编程方式访问它,您需要使用
eval(br$call$random)
为了得到~(1 | fac)
,也就是class"formula"
.
虽然我没有使用过 Stan,但这是 R 处理存储调用的方式中固有的问题。你可以看到它发生在 lm
,例如:
model <- function(formula)
{
lm(formula, data=mtcars)
}
m <- model(mpg ~ disp)
m$call$formula
# formula
最简单的解决方案是使用 substitute
构造调用以插入您要保留的实际值,而不是符号名称。在 lm
的情况下,这将类似于
model2 <- function(formula)
{
call <- substitute(lm(formula=.f, data=mtcars), list(.f=formula))
eval(call)
}
m2 <- model2(mpg ~ disp)
m2$call$formula
# mpg ~ disp
对于 Stan,你可以做到
stan_call <- substitute(br <- stan_gamm4(y ~ s(x0) + x1 + s(x2), data=dat, random=.rf,
chains=1, iter=200),
list(.rf=formula.rand))
br <- eval(stan_call)