Shiqing Fan
Shiqing Fan

Reputation: 708

R: Creating a generic function for ‘split’ from package ‘base’ in the global environment

For simplicity, I will use the following sample code :)

I had defined a S4 class test, and then as usual I adopted setMethod to write generic function split for class test:

# define a S4 class
setClass(
  Class="test",
  representation=representation(
   m = "matrix"
  )
)

# write generic function 'split' for S4 class 'test'
setMethod(f = "split", signature = c("test"), function(x, f) {
  split(x@m, f)
})

# call generic function for test
split(new("test", m=matrix(1:9,3)), c(1,2,3))

Run the code above and the R command line will give out message as follows:

Creating a generic function for ‘split’ from package ‘base’ in the global environment

and then the program output follows:

$`1`
[1] 1 4 7

$`2`
[1] 2 5 8

$`3`
[1] 3 6 9

It seems that output is correct. But my question is how to supress the message:

Creating a generic function for ‘split’ from package ‘base’ in the global environment

Thanks a lot :)

PS: I found that replace the definition of method split for S4 class test with the form of how we realize S3 generic methods as follows will do get rid of that message:

split.test <- function(x, f) {
  split(x@m, f)
}

However, I don't think it's a good idea to mix S3 and S4 :)

Upvotes: 3

Views: 732

Answers (1)

Bob Zimmermann
Bob Zimmermann

Reputation: 993

This is an unfortunate fact issue with S4 classes. The gold standard is frequently referred to as the Matrix package. They also cleverly avoid this issue: overloading rownames or colnames (defined in base) directly produces the identical warning. But inspection of these function reveals they are convenience functions to the dimnames function:

> colnames
function (x, do.NULL = TRUE, prefix = "col")
{
    if (is.data.frame(x) && do.NULL)
        return(names(x))
    dn <- dimnames(x)
# ...
}
> rownames
function (x, do.NULL = TRUE, prefix = "row")
{
    dn <- dimnames(x)
# ...
}
> dimnames
function (x)  .Primitive("dimnames")

The Matrix package avoids this issue by instead defining a generic against dimnames. As Michael above commented, your best bet is to overload the [ operator, which is similarly primitive:

> `[`
.Primitive("[")

Borrowing from the Matrix package again, one suggestion would be:

setMethod("[", signature(x = "sparseMatrix", i = "missing", j = "index",
             drop = "logical"), 
    function(x, i, j, ..., drop) {
       # add any behavior for ...
       `[`(x@m, i, j, drop=drop)
    }
)

This also adds a lot of free behavior from other generic functions using the [ operator.

Upvotes: 1

Related Questions