与此问题相关,但略有不同,希望更清楚.
我正在寻找一种干净的方式来正式注册S4和S3类的方法,但不依赖于可怕的S3-dot-naming-scheme进行调度.一个例子:
setClass("foo");
setClass("bar");
setGeneric("test", function(x, ...){
standardGeneric("test");
});
setMethod("test", "bar", function(x, ...){
return("success (bar).");
});
obj1 <- 123;
class(obj1) <- "bar";
test(obj1);
Run Code Online (Sandbox Code Playgroud)
这个例子展示了我们如何test为类的S3对象注册一个方法bar,而不需要命名该函数test.bar,这很好.但是,限制是如果我们以这种方式注册方法,它们将仅被分派到对象的第一个S3类.例如:
obj2 <- 123;
class(obj2) <- c("foo", "bar");
test(obj2);
Run Code Online (Sandbox Code Playgroud)
这不起作用,因为S4方法调度只会尝试类foo及其超类.如何扩展此示例,test以便bar在找不到合适的方法时自动选择方法foo?例如S3风格调度,但无需返回命名一切test.foo和test.bar?
总结一下:如何创建一个使用形式方法调度的泛型函数,但另外还要回到具有多个类的S3对象的对象的第二,第三等类.
我正在尝试添加一个merge需要为S4 的空间方法(因为它会调度两个不同对象的类型).
我尝试使用如下的早期解决方案:
#' Merge a SpatialPolygonsDataFrame with a data.frame
#' @param SPDF A SpatialPolygonsDataFrame
#' @param df A data.frame
#' @param \dots Parameters to pass to merge.data.frame
#'
#' @export
#' @docType methods
#' @rdname merge-methods
setGeneric("merge", function(SPDF, df, ...){
cat("generic dispatch\n")
standardGeneric("merge")
})
#' @rdname merge-methods
#' @aliases merge,SpatialPolygonsDataFrame,data.frame-method
setMethod("merge",c("SpatialPolygonsDataFrame","data.frame"), function(SPDF,df,...) {
cat("method dispatch\n")
})
Run Code Online (Sandbox Code Playgroud)
哪个工作:
x <- 1
class(x) <- "SpatialPolygonsDataFrame"
y <- data.frame()
> merge(x,y)
generic dispatch
method dispatch
Run Code Online (Sandbox Code Playgroud)
你将不得不相信我,如果x实际上是一个SPDF而不是伪造的,它不会返回你实际运行该代码时得到的插槽错误(或者没有,只是使用更宽松的通用以下不会返回错误).SPDF是一种痛苦的创造.
问题是它似乎覆盖了S3调度:
> …Run Code Online (Sandbox Code Playgroud) 我有两个类(a和b),我想+为它们定义方法.我需要两种类的四种可能组合的不同方法,即:
a + a method 1
a + b method 2
b + a method 3
b + b method 4
Run Code Online (Sandbox Code Playgroud)
我知道我可以使用S4进行多次调度,但我想知道是否有办法使用S3模拟这种行为.我的方法如下:
a <- "b"
class(a) <- "a"
b <- "e"
class(b) <- "b"
Ops.a <- function(e1, e2){
if (class(e1) == "a" &
class(e2) == "a")
print("a & a")
if (class(e1) == "a" &
class(e2) == "b")
print("a & b")
if (class(e1) == "b" &
class(e2) == "a")
print("b & a")
NULL
}
a …Run Code Online (Sandbox Code Playgroud) 我想定义自己的行为(方法),用于将data.frame与新S3类的对象相乘.但我无法弄清楚如何让方法调度以找到我的方法.有办法吗?
首先,我定义S3对象'a'(oldClass"A")和'df'(oldClass"data.frame"):
a <- 4
oldClass(a) <- "A"
df <- data.frame(x=1:2,y=3:4)
Run Code Online (Sandbox Code Playgroud)
然后我使用trace(Ops.data.frame,edit = TRUE)在第一行添加print("Ops.data.frame").这样,我知道何时调用Ops.data.frame.这是一个演示:
a*df
# [1] "Ops.data.frame"
# x y
# 1 4 12
# 2 8 16
Run Code Online (Sandbox Code Playgroud)
我可以为类"A"定义一个S3方法.
Ops.A <- function(e1, e2) {
print("Ops.A")
oldClass(e1) <- oldClass(e1)[oldClass(e1) != "A"]
oldClass(e2) <- oldClass(e2)[oldClass(e2) != "A"]
callGeneric(e1, e2)
}
Run Code Online (Sandbox Code Playgroud)
这被称为a而不是 df:
# This successfully calls Ops.A
a*a
# [1] "Ops.A"
# [1] 16
# But this throws an error
a*df
# Error in a * df : non-numeric argument …Run Code Online (Sandbox Code Playgroud)