Adding S4 dispatch to base R S3 generic

ε祈祈猫儿з 提交于 2019-11-27 15:14:24

问题


I am trying to add a spatial method to merge which needs to be S4 (since it dispatches on the types of two different objects).

I have tried using an earlier solution as follows:

#' 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")
})

Which does work:

x <- 1
class(x) <- "SpatialPolygonsDataFrame"
y <- data.frame()
> merge(x,y)
generic dispatch
method dispatch

You're going to have to trust me that if x is really a SPDF instead of a faked one, that it doesn't return the slot error which you get if you actually run that code (or don't, and just use the more permissive generic below which doesn't return the error). SPDFs are a pain to create.

The problem is that it seems to have overwritten S3 dispatch:

> merge(y,y)
generic dispatch
Error in function (classes, fdef, mtable)  : 
  unable to find an inherited method for function "merge", for signature "data.frame", "data.frame"

How do I avoid that? I've tried eliminating the function definition from setGeneric so that it simply reads setGeneric("merge") but that doesn't work either. Do I need to somehow import the merge S3 generic from base?


回答1:


The mis-dispatch occurs because the body of the generic is not "standard" (I think the rationale is that, since you've done something other than invoke standardGeneric("merge"), you know what you're doing so no automatic default; maybe I'm making this up and it's really a bug). Solutions are to set a standard generic allowing for the default dispatch

setGeneric("merge")

or to explicitly provide standard dispatch

setGeneric("merge", function(x, y, ...) standardGeneric("merge"))

or explicitly specify a default method

setGeneric("merge", function(x, y, ...){
  cat("generic dispatch\n")
  standardGeneric("merge")
}, useAsDefault=base::merge)


来源:https://stackoverflow.com/questions/12709933/adding-s4-dispatch-to-base-r-s3-generic

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!