我正在尝试更新我使用新类开发的新函数的调用。这种发展与Leish的文章"Creating R packages"中的linmod
非常相似。
在函数内部,调用与match.call()
一起存储。
当我尝试更新通话时,如下所示:
library(MASS)
fit <- linmod(Hwt~Bwt*Sex, data=cats)
update(fit, subset = -1)
我收到以下错误消息:
eval(expr,envir,enclos)中的错误: 找不到功能“linmod.formula”
问题似乎是match.call()
保存了完整的S3方法名称(linmod.formula
),而不仅仅是通用函数名称(linmod
),它可以完美地运行。
任何人都可以帮我解决这个问题吗?
答案 0 :(得分:0)
我知道修复此问题的最简单方法是导出方法。为此,您需要添加@export linmod.formula
。当然,通常不建议导出方法。
另一种选择是为update
创建方法。以下是update.default
的副本,另外还有一行:
#' @export
update.linmod <- function (object, formula., ..., evaluate = TRUE)
{
if (is.null(call <- getCall(object)))
stop("need an object with call component")
extras <- match.call(expand.dots = FALSE)$...
#call generic instead of method:
call[[1]] <- quote(linmod)
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
}
我不喜欢这两个选项,并且会避免使用linmod
函数的方法。你的默认方法对我来说似乎毫无用处。请注意,例如,lm
不是S3泛型。
PS:update
没有subset
参数。
答案 1 :(得分:0)
由于这里还没有提到这一点,而且它是?update
中明确推荐的方法:为getCall
编写一个方法。来自?update
:
update()
和类似函数中的“提取调用”使用 getCall()
,它本身是一个 (S3) 泛型函数,带有一个简单的获取 x$call 的默认方法。因此,update()
通常会在新模型类上工作(通过其默认方法),或者自动运行,或者通过为该类提供简单的 getCall()
方法。
因此,在您的包裹中,如果您有:
#' @export
f <- function(x) {
UseMethod("f")
}
#' @export
f.bar <- function(x) {
structure(list(x = x, call = match.call()), class = "fbar")
}
#' @export
#' @importFrom stats getCall
getCall.fbar <- function(x) {
x$call[[1L]] <- quote(f) # replacing `f.bar`
x$call
}
然后,在您的脚本中,您可以:
x1 <- structure(1, class = "bar")
x2 <- structure(2, class = "bar")
fx1 <- f(x = x1)
fx2 <- update(fx1, x = x2)
fx1
# $x
# [1] 1
# attr(,"class")
# [1] "bar"
#
# $call
# f.bar(x = x1)
#
# attr(,"class")
# [1] "fbar"
fx2
# $x
# [1] 2
# attr(,"class")
# [1] "bar"
#
# $call
# f.bar(x = x2)
#
# attr(,"class")
# [1] "fbar"