Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

R S4 setMethod '[' distinguish missing argument?

Tags:

oop

r

s4

Apologies for the title, not sure how else to phrase this question.

If I want to create setMethod on a class how can I distinguish between the similar cases of mat[i,] and mat[i]?

I know for the former I can use:

setMethod("[",
    signature(x = "foo", j = "missing", drop = "missing"),
    function(x,i,j,drop) return(myFunc(x,i))
)

How can I set a method to distinguish the latter where I wouldn't want to select rows but elements as in the base matrix class?

Looking at the ?[ documentation I expected something like the following would work:

setMethod("[",
    signature(x = "foo", i = "numeric"),
    function(x,i,j,drop) return(myFunc(x,i))
)

but it conflicts with any previously defined methods where j and drop are missing.

The idea being the same as

mat <- matrix(seq(9), 3, 3)

mat[c(1,3),]
1 4 7
3 6 9

mat[c(1,3)]
[1] 1 3
like image 264
cdeterman Avatar asked Jun 02 '16 16:06

cdeterman


1 Answers

You will find a lot of examples in the Matrix package. It uses S4 and implements new classes and methods for matrices. As far as I know there is no way to declare what you are looking for in the signature. Instead you have to use the function nargs to distinguish between mat[1] and mat[1, ]. Here is an example how to do that:

setClass("foo", slot = c(mat = "matrix"))

setMethod(
  "[",
  signature(x = "foo", i = "missing", j = "missing", drop = "missing"),
  function(x, i, j, drop = FALSE) {
    x
  }
)

setMethod(
  "[",
  signature(x = "foo", i = "numeric", j = "missing", drop = "missing"),
  function(x, i, j, ..., drop) {
    if (nargs() == 3) x@mat[i, ]
    else x@mat[i]
  }
)

setMethod(
  "[",
  signature(x = "foo", i = "numeric", j = "numeric", drop = "missing"),
  function(x, i, j, ..., drop) {
    x@mat[i, j]
  }
)

mat <- new("foo", mat = matrix(seq(9), 3, 3))

mat[]
mat[2:5]
mat[1:2, ]
mat[1:2, 2]

However, it would be easier if you directly extend the base class 'matrix' (or 'Matrix' from the Matrix package) and do something like

setClass("Matrix", contains = "matrix")

since you get these methods for free. Note for example, that in the implementation above, you still have to take care of the argument drop. And basically you have to reimplement what is already there.

like image 103
Sebastian Avatar answered Oct 22 '22 02:10

Sebastian