[R] setMethod "[" - extract by names within Slot

Martin Morgan mtmorgan at fhcrc.org
Sun Oct 23 19:10:10 CEST 2011


On 10/22/2011 08:03 AM, Omphalodes Verna wrote:
> Thanks Martin.
>
> Here is my ''updated'' code.
>
> setClass("myClass", representation(ID.r = "numeric", ID.c = "character", DAT = "matrix"))
>
> to.myClass<- function(ID.r, ID.c, DAT) {
>      out<- new("myClass", ID.r = ID.r, ID.c = ID.c, DAT = DAT)
>      return(out)
>        }
>
> setMethod("[", "myClass", function(x, i, j, drop = TRUE) {
>      x at ID.r<- x at ID.r[i]
>      x at ID.c<- x at ID.c[j]
>      out.0<- x at DAT[i,j]
>      out.1<- to.myClass(x at ID.r, x at ID.c, as.matrix(out.0))
>      return(out.1)
>    })
>
> setMethod("[", c("myClass", "ANY", "character"),
>      function(x, i, j, ..., drop = TRUE) {
>      if(missing(i)) {x at ID.r<- x at ID.r} else {x at ID.r<- x at ID.r[i]}
>      j<- which(j == x at ID.c)
>      x at ID.c<- x at ID.c[j]
>      out.0<- x at DAT[i, j]
>      out.1<- to.myClass(x at ID.r, x at ID.c, as.matrix(out.0))
>      return(out.1)
>        })
>
> a<- to.myClass(seq(1,25), c("A","A","B","B"), matrix(rnorm(100), nrow = 25))
> a
>
> a[1:20, ] #works
> a[, 1:3] #works
> a[1:10, 1:3] #works
> a[, "A"] #works
> a[5:20, "B"] #works
>
> It works, but Is it normal to write two codes for setMethod???

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

> Nice weekend, OV
>
>
> ________________________________
> From: Martin Morgan<mtmorgan at fhcrc.org>
>
> Cc: "r-help at r-project.org"<r-help at r-project.org>
> Sent: Saturday, October 22, 2011 3:50 PM
> Subject: Re: [R] setMethod "[" - extract by names within Slot
>
> On 10/22/2011 02:11 AM, Omphalodes Verna wrote:
>> Hi R-helper!
>>
>> I have problem with setMethods for "[". Here is example :
>>
>> setClass("myClass", representation(ID.r = "numeric", ID.c = "character", DAT = "matrix"))
>>
>> to.myClass<- function(ID.r, ID.c, DAT) {
>>        out<- new("myClass", ID.r = ID.r, ID.c = ID.c, DAT = DAT)
>>        return(out)
>>          }
>>
>> setMethod("[", "myClass", function(x, i, j, drop) {
>>        x at ID.r<- x at ID.r[i]
>>        x at ID.c<- x at ID.c[j]
>>        out.0<- x at DAT[i,j]
>>        out.1<- to.myClass(x at ID.r, x at ID.c, as.matrix(out.0))
>>        return(out.1)
>>      })
>>
>> a<- to.myClass(seq(1,25), c("A","A","B","B"), matrix(rnorm(100), nrow = 25))
>> a
>>
>>
>> a[1:20, ] #works
>> a[, 1:3] #works
>> a[1:10, 1:3] #works
>>
>> a[, "A"] #not works
>
> thinking about your code, this is the same as
>
>>     ID.c = c("A","A","B","B")
>>     j = "A"
>>     ID.c[j]
> [1] NA
>
>
>>
>> What is solution to write "[" methods for extraction by names of Slot "ID.c"
>
> Maybe (untested)
>
>     setMethod("[", c("myClass", "ANY", "character"),
>         function(x, i, j, ..., drop=TRUE) {
>             j = match(j, x at ID.c)
>             x[i, j, ..., drop=TRUE]
>        })
>
>>
>> Thanks all. OV
>>
>>      [[alternative HTML version deleted]]
>>
>>
>>
>>
>> ______________________________________________
>> R-help at r-project.org mailing list
>> https://stat.ethz.ch/mailman/listinfo/r-help
>> PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
>> and provide commented, minimal, self-contained, reproducible code.
>
>
>
>
> ______________________________________________
> R-help at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-help
> PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
> and provide commented, minimal, self-contained, reproducible code.


-- 
Computational Biology
Fred Hutchinson Cancer Research Center
1100 Fairview Ave. N. PO Box 19024 Seattle, WA 98109

Location: M1-B861
Telephone: 206 667-2793



More information about the R-help mailing list