R-片状S4方法调度



我正在测试,以查看我是否可以支持使用 cplm package Forn for emmeans 中的模型,然后我遇到了一些非常奇怪的terms方法的行为。这是一个示例:

library(emmeans)
library(cplm)
data(mtcars)
m <- cpglm(mpg ~ cyl + disp + hp, data = mtcars)

功能emmeans:::recover_data.lm似乎有一些正常工作的承诺。它只是在对象上调用terms方法并将其传递给其他功能。但是,它行不通:

> emmeans:::recover_data.lm(m)
 Error in slot(x, name) : 
  no slot of name "terms" for this object of class "cpglm" 

进一步挖掘,我验证了terms()确实在全球环境中工作:

> terms(m)
mpg ~ cyl + disp + hp
... (remaining lines excluded) ...

但是,它在recover_data.lm中不起作用:

> debug(emmeans:::recover_data.lm)
> emmeans:::recover_data.lm(m)
    ...
Browse[2]> terms(object)
Error in slot(x, name) : 
  no slot of name "terms" for this object of class "cpglm"
Browse[2]> getMethod("terms", "cpglm")
Error in getMethod("terms", "cpglm") : 
  no method found for function 'terms' and signature cpglm

但是...

Browse[2]> getMethod("terms", "cplm")  ## cpglm inherits from cplm
Method Definition:
function (x, ...) 
attr(x@model.frame, "terms")
    ... etc. ...
Browse[2]> methods("terms")
[1] terms,ANY-method  terms,cplm-method terms.default*    terms.formula*    terms.gls*       
[6] terms.merMod*     terms.terms*     
see '?methods' for accessing help and source code
Browse[2]> selectMethod("terms", "cpglm")
Method Definition:
function (x, ...) 
attr(x@model.frame, "terms")
    ... etc. ...

因此,在 emmeans 的命名空间中,我可以验证我们"知道" cpglm对象有一个terms方法,我们可以通过selectMethod()或通过getMethod()或仅通过CC_8找到它调用terms()。这很奇怪,尤其是因为selectMethod的文档似乎保证它应该有效:

功能selectMethod()返回将选择的方法 如果该参数已指定的类 signature

最后,我能够验证这似乎与派遣S3方法的冲突有关:

> stats::terms(m)
Error in slot(x, name) : 
  no slot of name "terms" for this object of class "cpglm"

是否有一种方法可以使我的软件包 Emmeans 在有S3和S4方法的混合时正确工作;特别是在S3方法之前查找S4方法?

来自 Methods_for_S3中的文档条目:

定义S3和S4方法的原因如下:

  1. 如果直接调用S3通用函数,则不会仅看到S4方法。例如,如果某些函数从一个不会使该函数成为S4通用的软件包中的某些函数调用((。

cplm软件包导出了terms的S4方法,但不是一个用于S3的人您可以在这里看到。当您附加cplm时,这会自动使terms成为S4通用。但是,emmeans调用stats的S3通用,这就是导致问题的原因。

您可以通过在全球环境中定义派遣到S4通用的全球环境中的S3通用:

terms.cpglm <- function(x, ...) {
    cplm::terms(x, ...)
}

但是,您应该让cplm维护者知道,如果他将S3通用性转换为S4,则应定义S3和S4方法。

最新更新