Как правильно передать формулы, связанные с именем переменной со случайными эффектами, в подогнанные регрессионные модели в `R`? - PullRequest
0 голосов
/ 12 мая 2018

У меня сейчас проблема в том, что я должен предварительно указать свои формулы перед отправкой их в функцию регрессии. Например, используя функцию stan_gamm4 в R, мы имеем следующий пример:

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? Благодарю.

Ответы [ 3 ]

0 голосов
/ 12 мая 2018

ИМХО, это не проблема с stan_gamm4. Во втором примере, если вы затем выполните

class(br$call$random)

вы увидите, что это класс "name". Так что это не так, как если бы $call - это просто какой-то список с вещами в нем. Чтобы получить к нему программный доступ в целом, необходимо оценить это с помощью

eval(br$call$random)

для получения ~(1 | fac), который имеет класс "formula".

0 голосов
/ 12 мая 2018

Хотя я не использовал 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_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)
0 голосов
/ 12 мая 2018

Если я правильно понимаю, ваша проблема не в том, что stan_gamm4 может вычислять неверные результаты (что не так, как я понял), а только в том, что br$call$random относится к имени переменной, а не к формуле.Это кажется проблематичным для дальнейшей постобработки модели.

Поскольку stan_gamm4 использует match.call внутри, чтобы найти вызов, я не знаю способа указать модель по-другому для получения«правильно» 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)

и продолжить то, что вы делаете.

...