这是一个特别模糊且无用的错误,但如果您了解what a "closure" is,那么它可能会提供有关查找位置的见解。不幸的是,在这里找到它有点困难......
TL;DR
将您的变量从formula 重命名为任何其他不是函数名称的名称。例如,如果您使用 frm <- paste(...),您的代码就可以正常工作。
注意:这是一个经典示例,说明了为什么您应该避免将变量命名为与函数相同的名称。通常你会看到命名为data 的变量。在这种情况下,formula 是一个函数,由于包搜索路径,它没有按您期望的顺序找到。
说明
要找出原因,首先我们需要调试被调用的特定函数。我们可以使用debug(boxcox) 并逐步进入它,或者我们可以使用debug(MASS:::boxcox.lm) 来确保我们调试正确的。无论如何...
boxcox(M)
# debugging in: boxcox.lm(M)
# debug: {
# m <- length(lambda)
# if (is.null(object$y) || is.null(object$qr))
# object <- update(object, y = TRUE, qr = TRUE, ...)
# result <- NextMethod()
# if (plotit)
# invisible(result)
# else result
# }
单步执行,调用update 失败。信息量不是很大,我们需要介入其中。我们可以使用s 来单步执行该函数。 (顺便说一下,它使用的是MASS:::update.loglm,而不是导出函数。)
# Browse[2]>
s
# debugging in: update(object, y = TRUE, qr = TRUE, ...)
# debug: UseMethod("update")
# Browse[3]>
s
# debugging in: update.default(object, y = TRUE, qr = TRUE, ...)
# debug: {
# if (is.null(call <- getCall(object)))
# stop("need an object with call component")
# extras <- match.call(expand.dots = FALSE)$...
# if (!missing(formula.))
# call$formula <- update.formula(formula(object), formula.)
# if (length(extras)) {
# existing <- !is.na(match(names(extras), names(call)))
# for (a in names(extras)[existing]) call[[a]] <- extras[[a]]
# if (any(!existing)) {
# call <- c(as.list(call), extras[!existing])
# call <- as.call(call)
# }
# }
# if (evaluate)
# eval(call, parent.frame())
# else call
# }
逐步执行此操作,在最后一个命令eval(call, parent.frame()) 上失败。仍然不是很有帮助,但是在进行故障排除时查看 R 认为它正在使用的变量很有用。例如,之前:
# Browse[2]>
object
# Call:
# lm(formula = formula, data = data1)
# Coefficients:
# (Intercept) I(cyl^2) I(disp^2) I(hp) I(drat) I(hp * drat) cyl
# 3.274e+00 -2.006e-02 9.589e-06 -1.250e-02 2.388e-01 5.869e-04 4.034e-01
# hp disp drat cyl:hp hp:disp cyl:drat disp:drat
# NA -9.728e-03 NA 2.122e-03 -2.418e-05 -1.155e-01 2.064e-03
好的,看起来是正确的。接下来,请意识到eval 调用正在尝试调用以前的模型并对其进行更新。
# Browse[4]>
call
# lm(formula = formula, data = data1)
这看起来与我们第一次调用它的方式相似。但是,查看实际变量,data1 看起来是正确的,但是...
# Browse[4]>
formula
# function (x, ...)
# UseMethod("formula")
# <bytecode: 0x000000001a5c20a0>
# <environment: namespace:stats>
哦。因此,在最近对lm 的调用中引用的formula 没有返回到原始调用环境,即使使用eval(...,parent.frame())。
如果您改为使用:
(frm <- paste( "I(log(Y)) ~" , paste(c(E_eff, G_eff_1, G_eff_2, G_eff_3, E_vs_G), collapse = "+")))
M <- lm(frm, data=data1)
然后一切正常。