如何解决在 mgcv::gam() 包装器中传递偏移参数
我围绕 mgcv::gam()
编写了一个包装函数,以将模型直接写入磁盘并做一些额外方便的事情。到目前为止,一切都很好,每个参数都被传递并且有效。除了,当我添加要传递给 mgcv::gam(offset = )
的偏移参数时。下面是一些示例代码。
require(mgcv)
gam1 = function(form,data,family,knots = NULL) {
gam(formula = form,knots = knots,data = data,family = family)
}
gam1(Sepal.Length ~ s(Sepal.Width),data = iris,family = 'gaussian')
参数传递给 gam()
(例如节、家庭)。作品。但是,如果我将 offset_
添加到聚会中,它不会传递但会引发错误:
gam2 = function(form,knots = NULL,offset_ = NULL) {
gam(formula = form,family = family,offset = offset_)
}
gam2(Sepal.Length ~ s(Sepal.Width),family = 'gaussian',offset_ = NULL)
offset_
未传递并引发此错误:
Error in eval(extras,env) : object 'offset_' not found
。如果我改用 offset
,它会抛出这个错误:invalid type (closure) for variable '(offset)'
。
问:为什么我的包装器无法传递 offset_
?我怎样才能让它运行?
mf$drop.unused.levels <- drop.unused.levels
mf[[1]] <- quote(stats::model.frame) ## as.name("model.frame")
pmf <- mf
mf <- eval(mf,parent.frame()) # the model frame Now contains all the data
解决方法
问题在于范围界定。 gam()
首先在 formula
参数中查找 offset
和 data
中的变量,然后在附加到 formula
的环境中查找。通常这就是创建 formula
的环境;在您的示例中,这将是全球环境。
例如,您应该能够通过将 offset_
变量添加到 data
的本地副本来使事情工作
gam3 <- function(form,data,family,knots = NULL,offset_ = NULL) {
if (is.null(offset_)) {
gam(formula = form,data = data,family = family,offset = NULL)
} else {
data$offset_copy <- offset_
gam(formula = form,offset = offset_copy)
}
}
如果 data
有一个名为 offset_copy
的列,这将覆盖它,所以一定要使用一个不在 data
中的名称。
编辑添加:@GavinSimpson 建议修改他的答案中的公式,以避免 predict()
出现问题。我建议进行与他使用的不同的修改:不要解析公式和偏移量,只需直接修改公式即可。例如,
fun <- function(form,offset_ = NULL,...) {
## capture what was passed to offset_,unevaluated
off <- substitute(offset_)
if (!is.null(offset_)) { # need to add offset
form[[3]] <- call("+",form[[3]],call("offset",off))
}
## fit and return model
gam(form,...)
}
函数 call()
创建了一个调用,因此 form[[3]]
行将公式的 RHS 替换为对旧 RHS 的 "+"
的未评估调用,以及对 {{1} 的调用}} 包含偏移量。
这样做而不是解析的优点是它应该正确处理异常情况,例如可能会分解为几行的极长公式或偏移量,或者环境很重要的公式,因为此版本保持环境不变。
,@user2554330 解释了原因和解决方法。我想提出一种完全替代的方法。
通常最好在公式中包含偏移量。如果你不这样做,那么它会在 predict()
之类的东西中被忽略。
如果 offset_
不是 NULL
,我建议您在公式中添加偏移量。像这样的工作:
fun <- function(form,...) {
## capture what use passed to offset_,unevaluated
off <- deparse(substitute(offset_))
new_form <- form # copy as we may be modifying formula
if (!is.null(offset_)) { # need to add offset
form <- as.character(form) # coerce to character
## paste some bits of the formula back together
new_form <- paste(form[2],form[1],form[3])
## add the offset
off_form <- paste0("offset(",off,")")
new_form <- paste(new_form,off_form,sep = " + ")
## coerce to formula
new_form <- as.formula(new_form)
}
## fit and return model
gam(new_form,...)
}
这里正在使用
N <- 50
effort <- rep(5,N)
df <- data.frame(y = runif(N),x = runif(N),z = runif(N))
fun(y ~ s(x) + s(z),offset_ = log(effort),data = df)
返回:
>
Family: gaussian
Link function: identity
Formula:
y ~ s(x) + s(z) + offset(log(effort))
Estimated degrees of freedom:
1 1 total = 3
GCV score: 0.08046669```
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。