#r #function #nlme #mgcv
#r #функция #nlme #mgcv
Вопрос:
Я пытаюсь создать свою собственную функцию, которая содержит 1.) функцию mgcv gamm и 2.) вложенный аргумент автокорреляции (ARMA). Я получаю сообщение об ошибке, когда пытаюсь запустить функцию следующим образом:
df <- AirPassengers
df <- as.data.frame(df)
df$month <- rep(1:12)
df$yr <- rep(1949:1960,each=12)
df$datediff <- 1:nrow(df)
try_fxn1 <- function(dfz, colz){gamm(dfz[[colz]] ~ s(month, bs="cc",k=12) s(datediff,bs="ts",k=20), data=dfz,correlation = corARMA(form = ~ 1|yr, p=2))}
try_fxn1(df,"x")
Ошибка в eval (predvars, data, env): объект ‘dfz’ не найден
Я знаю, что проблема связана с корреляционной частью формулы, поскольку, когда я запускаю ту же функцию без включенной структуры корреляции (как показано ниже), функция ведет себя так, как ожидалось.
try_fxn2 <- function(dfz, colz){gamm(dfz[[colz]] ~ s(month, bs="cc",k=12) s(datediff,bs="ts",k=20), data=dfz)}
try_fxn2(df,"x")
Любые идеи о том, как я могу изменить try_fxn1, чтобы функция вела себя так, как ожидалось? Спасибо!
Ответ №1:
Вы путаете вектор с символическим представлением этого вектора при построении формулы.
Вы не хотите dfz[[colz]]
, чтобы в качестве ответа в формуле, вы хотите x
или что бы вы ни установили colz
. То, что вы получаете, это
dfz[[colz]] ~ ...
когда то, что вы действительно хотите, это переменная colz
:
colz ~ ...
И вам не нужен литерал colz
, но все, что colz
оценивается. Для этого вы можете создать формулу, вставив части вместе:
fml <- paste(colz, '~ s(month, bs="cc", k=12) s(datediff,bs="ts",k=20)')
Это превращается colz
в то, что оно хранило, а не в литерал colz
:
> fml
[1] "x ~ s(month, bs="cc", k=12) s(datediff,bs="ts",k=20)"
Затем преобразуйте строку в объект формулы, используя formula()
или as.formula()
.
Тогда окончательное решение:
fit_fun <- function(dfz, colz) {
fml <- paste(colz, '~ s(month, bs="cc", k=12) s(datediff,bs="ts",k=20)')
fml <- formula(fml)
gamm(fml, data = df, correlation = corARMA(form = ~ 1|yr, p=2))
}
Это действительно не проблема с corARMA()
part, кроме того, что запускает несколько иной код вычисления для формулы. Руководящая мантра здесь заключается в том, чтобы всегда получать формулу так, как вы бы ее вводили, если бы не программировали с помощью формул. Вы бы никогда (или никогда не должны) писать формулу типа
gamm(df[[var]] ~ x s(z), ....)
Хотя это может сработать в некоторых настройках, оно с треском провалится, если вы когда-нибудь захотите использовать predict()`, и оно терпит неудачу, когда вам нужно сделать что-то более сложное.