如何通过调度方法的调用并与默认值结合?

How to pass through call of dispatched method and combine with defaults?

提问人:jay.sf 提问时间:10/20/2022 最后编辑:jay.sf 更新时间:10/20/2022 访问量:54

问:

我有一个通用函数,一个相应的默认方法,例如一个公式方法。如果调度了默认方法,则 to 应作为 ibute 返回,而 if 已调度,并且参数应替换为 rmula 参数。此外,还应返回默认值(在这两种方法中),即使用户未显式指定。foocallfoo.defaultattrfoo.formulaXyfofoo.default

它看起来已经不太糟糕了,但到目前为止,我无法将呼叫从 传递到 .foo.formulafoo.default

foo <- function(x, ...) UseMethod('foo')

foo.formula <- function(fo, data, ...) {
  .cl <- match.call()
  y <- model.response(model.frame(fo, data))
  X <- model.matrix(fo, data)
  foo.default(X, y, .cl=.cl)
}

foo.default <- function(X, y, bar=FALSE, method='1A', beta=2, ...) {
  if (!exists('.cl')) .cl <- match.call()
  fa <- formalArgs(foo.default)
  m <- match(names(.cl), fa, nomatch=0)
  .cl <- c(as.list(.cl), as.list(args(foo.default))[-m])
  .cl[[1]] <- as.name('foo')
  `attr<-`(lm.fit(X, y)$coefficients, 'call', as.call(.cl))
}

foo(X1, y1)
# (Intercept)          hp 
# 30.09886054 -0.06822828 
# attr(,"call")
# foo(X = X1, y = y1, bar = FALSE, method = "1A", beta = 2, 
#             ... = , NULL)

foo(mpg ~ hp, mtcars)
# (Intercept)          hp 
# 30.09886054 -0.06822828 
# attr(,"call")
# foo(X = X, y = y, .cl = .cl, bar = FALSE, method = "1A", 
#             beta = 2, ... = , NULL)

所需输出约为:

foo(X1, y1)
# (Intercept)          hp 
# 30.09886054 -0.06822828 
# attr(,"call")
# foo(X = X1, y = y1, bar = FALSE, method = "1A", beta = 2, ...)

foo(mpg ~ hp, mtcars)
# (Intercept)          hp 
# 30.09886054 -0.06822828 
# attr(,"call")
# foo(fo = mpg ~ hp, data = mtcars, bar = FALSE, method = '1A', beta = 2, ...)

我该怎么做?


数据:

y1 <- c(`Mazda RX4` = 21, `Mazda RX4 Wag` = 21, `Datsun 710` = 22.8, 
`Hornet 4 Drive` = 21.4, `Hornet Sportabout` = 18.7, Valiant = 18.1, 
`Duster 360` = 14.3, `Merc 240D` = 24.4, `Merc 230` = 22.8, `Merc 280` = 19.2, 
`Merc 280C` = 17.8, `Merc 450SE` = 16.4, `Merc 450SL` = 17.3, 
`Merc 450SLC` = 15.2, `Cadillac Fleetwood` = 10.4, `Lincoln Continental` = 10.4, 
`Chrysler Imperial` = 14.7, `Fiat 128` = 32.4, `Honda Civic` = 30.4, 
`Toyota Corolla` = 33.9, `Toyota Corona` = 21.5, `Dodge Challenger` = 15.5, 
`AMC Javelin` = 15.2, `Camaro Z28` = 13.3, `Pontiac Firebird` = 19.2, 
`Fiat X1-9` = 27.3, `Porsche 914-2` = 26, `Lotus Europa` = 30.4, 
`Ford Pantera L` = 15.8, `Ferrari Dino` = 19.7, `Maserati Bora` = 15, 
`Volvo 142E` = 21.4)

X1 <- structure(c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 110, 110, 93, 110, 
175, 105, 245, 62, 95, 123, 123, 180, 180, 180, 205, 215, 230, 
66, 52, 65, 97, 150, 150, 245, 175, 66, 91, 113, 264, 175, 335, 
109), dim = c(32L, 2L), dimnames = list(c("Mazda RX4", "Mazda RX4 Wag", 
"Datsun 710", "Hornet 4 Drive", "Hornet Sportabout", "Valiant", 
"Duster 360", "Merc 240D", "Merc 230", "Merc 280", "Merc 280C", 
"Merc 450SE", "Merc 450SL", "Merc 450SLC", "Cadillac Fleetwood", 
"Lincoln Continental", "Chrysler Imperial", "Fiat 128", "Honda Civic", 
"Toyota Corolla", "Toyota Corona", "Dodge Challenger", "AMC Javelin", 
"Camaro Z28", "Pontiac Firebird", "Fiat X1-9", "Porsche 914-2", 
"Lotus Europa", "Ford Pantera L", "Ferrari Dino", "Maserati Bora", 
"Volvo 142E"), c("(Intercept)", "hp")), assign = 0:1)
R 方法 属性 调用 调度

评论

0赞 Chris 10/20/2022
对于我们这些含糊不清的人来说,什么在 vs 中折腾。= , NULL)...)
0赞 jay.sf 10/20/2022
@Chris 名为 In 的参数为空,不显示任何值。来自最后一个元素 what yields which is unnamed 和 .as.list(.cl)"..."NULLargsNULL

答:

1赞 Maurits Evers 10/20/2022 #1

这个怎么样?

foo.default <- function(X, y, bar=FALSE, method='1A', beta=2, ...) {
    ell <- list(...)
    fa <- Filter(Negate(is.null), as.list(args(foo.default)))
    if (!exists('.cl', where = ell)) {
        .cl <- as.list(match.call())
        m <- match(names(.cl), names(fa), nomatch = 0)
        .cl <- c(.cl, fa[-m])
    } else {
        .cl <- c(as.list(ell$.cl), fa[-c(1, 2)])
    }
    `attr<-`(lm.fit(X, y)$coefficients, 'call', as.call(.cl))
}

foo(X1, y1)
#(Intercept)          hp 
#30.09886054 -0.06822828 
#attr(,"call")
#foo.default(X = X1, y = y1, bar = FALSE, method = "1A", beta = 2, 
#            ... = )

foo(mpg ~ hp, mtcars)
#(Intercept)          hp 
#30.09886054 -0.06822828 
#attr(,"call")
#foo.formula(fo = mpg ~ hp, data = mtcars, bar = FALSE, method = "1A", 
#            beta = 2, ... = )

几点评论:

  1. 这里有一点(小的?)尴尬:Inside ,不包括前两个参数和何时首先被调度,在这里是硬编码的。所以我不确定当你引入另一种方法时,这将如何概括,例如.只要替换前两个参数就可以了;如果没有,则需要更多的工作。elseXyfoo.defaultfoo.formulafoo.bar(df, ...)dffoo.default

  2. 我不完全明白从哪里来。我认为这是因为返回在强制时会变成最后一个元素。无论哪种方式,都可以用 删除它。NULLas.list(args(foo.default))argsNULLNULLas.listFilter(Negate(is.null), ...)

  3. 我还没有整理省略号的论点。而不是我拿走它,你想要里面.... = ...call

评论

1赞 jay.sf 10/20/2022
很好的答案,关键点是哪个很棒。毕竟,报告中实际上并不需要。 最后回来真的很奇怪,但我们可以忍受它。ell <- list(...)...callas.list(args(.))NULL