我正在测试,以查看我是否可以支持使用 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方法的原因如下:
- 如果直接调用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方法。