Skip to content
Prev 275253 / 398506 Next

setMethod "[" - extract by names within Slot

On 10/22/2011 08:03 AM, Omphalodes Verna wrote:
Hi --

I defined the class as

setClass("A",
          representation=representation(
            rid="integer",
            cid="character",
            elt="matrix"))

A common pattern is that the methods provide a 'facade' that make 
different user inputs conform to a particular signature, and then all 
invoke a common function where the complicated work is done; sometimes 
the function is one of the methods. Here's where I'd do the work

setMethod("[", c("A", "numeric", "character"),
     function(x, i, j, ..., drop=TRUE)
{
     cidx <- match(j, x at cid)
     if (any(is.na(cidx)))
         stop("invalid 'j'")
     initialize(x, rid=x at rid[i], cid=x at cid[cidx],
                elt=x at elt[i, cidx, drop=FALSE])
})

This uses 'initialize' as a copy constructor. Any complicated code for 
subsetting would be added to this method, and only in one place.

For "[" a minimal facade needs to handle the cases where i, j, or both 
are missing -- these are the facade, doing some minimal work to make it 
possible to invoke the underlying work-horse


setMethod("[", c("A", "missing", "character"),
     function(x, i, j, ..., drop=TRUE)
{
     x[x at rid, j, ..., drop=drop]
})

setMethod("[", c("A", "numeric", "missing"),
     function(x, i, j, ..., drop=TRUE)
{
     x[i, x at cid, ..., drop=drop]
})

setMethod("[", c("A", "missing", "missing"),
     function(x, i, j, ..., drop=TRUE)
{
     x[x at rid, x at cid, ..., drop=drop]
})

You also want to use a numeric (actually, integer) value for the second 
argument. This requires two more facade methods, distinguishing between 
a 'missing' first argument and an 'ANY' first argument

setMethod("[", c("A", "ANY", "numeric"),
     function(x, i, j, ..., drop=TRUE)
{
     x[i, x at cid[j], ..., drop=TRUE]
})

setMethod("[", c("A", "missing", "numeric"),
     function(x, i, j, ..., drop=TRUE)
{
     x[, x at cid[j], ..., drop=drop]
})

Here are some tests

a <- new("A", rid=1:5, cid=c("A", "B", "C"), elt=matrix(1:15, nrow=5))
a[1:2, "A"]

a[1:2,]
a[,"A"]
a[,]

a[1:2, 1:2]
a[,1:2]

The use of 'numeric' is a little loose, allowing a[1.1,] for instance, 
but a stricter 'integer' is probably too inconvenient for the user. 
'rid' is a bit weird -- is the user supposed to index it (x at rid[i], 
x at elt[i,]) or match it (ridx = match(i, x at rid); x at rid[ridx], x at elt[ridx,])?

Martin