Swinton, Jonathan
2004-Apr-19 12:16 UTC
[R] How to write an S4 method for sum or a Summary generic
If I have a class Foo, then i can write an S3 method for sum for it:>setClass("Foo",representation(a="integer"));aFoo=new("Foo",a=c(1:3,NA)) >sum.Foo <- function(x,na.rm){print(x);print(na.rm);sum(x at a,na.rm=na.rm)} >sum(aFoo)But how do I write an S4 method for this? All my attempts to do so have foundered. For example>setMethod("sum",signature("Foo","logical"),function(x,na.rm){print(x);print(na.rm);sum(x at a,na.rm=na.rm)} creates a method which seems to despatch on na.rm="Foo":> getMethods("sum")na.rm = "ANY": function (..., na.rm = FALSE) .Internal(sum(..., na.rm = na.rm)) na.rm = "Foo": function (..., na.rm = FALSE) { .local <- function (x, na.rm) { print(x) print(na.rm) sum(x at a, na.rm = na.rm) } .local(..., na.rm = na.rm) } na.rm = "missing": function (..., na.rm = FALSE) .Internal(sum(..., na.rm = na.rm)) ##: (inherited from na.rm = "ANY") Pages 350-352 of the Green book discuss at some length how to write a generic function for Summary group generics which uses tail recursion to allow the correct method to be called on each member of a ... argument list. But it gives no examples of what individual method functions need to look like. Any ideas or a place to look for working code? Jonathan Swinton, Statistical Scientist, Computational Biology, Pathway Analysis, Global Sciences and Information, AstraZeneca.
Douglas Bates
2004-Apr-19 16:37 UTC
[R] How to write an S4 method for sum or a Summary generic
"Swinton, Jonathan" <Jonathan.Swinton at astrazeneca.com> writes:> If I have a class Foo, then i can write an S3 method for sum for it: > > >setClass("Foo",representation(a="integer"));aFoo=new("Foo",a=c(1:3,NA)) > >sum.Foo <- function(x,na.rm){print(x);print(na.rm);sum(x at a,na.rm=na.rm)} > >sum(aFoo) > > But how do I write an S4 method for this? All my attempts to do so have > foundered. For example > >setMethod("sum",signature("Foo","logical"),> function(x,na.rm){print(x);print(na.rm);sum(x at a,na.rm=na.rm)} > creates a method which seems to despatch on na.rm="Foo":There is no x argument in the generic so you can't dispatch on it.> sumfunction (..., na.rm = FALSE) .Internal(sum(..., na.rm = na.rm))
Swinton, Jonathan
2004-Apr-21 10:10 UTC
[R] RE: How to write an S4 method for sum or a Summary generic
I asked last week if anyone knew how to define an S4 method for "sum" or any member of the "Summary" group generics. Doug Bates pointed out that >There is no x argument in the generic so you can't dispatch on it. > sum function (..., na.rm = FALSE) .Internal(sum(..., na.rm = na.rm)) but I don't know if he meant to imply that therefore there was no way of doing this. I had no other replies. I have now grepped all the R sources, and all the CRAN or Bioconductor packages, and found no example of any setMethod("sum or setMethod("Summary. (Moreover it seems to me that the implementation of setGeneric("max" proposed on p351 of the Green Book, and designed explicitly to allow S4 methods to be written for "Summary" group generics, is not in fact implemented in R, but I don't understand the code well enough.) Is it the opinion of r-help or the R core that it is not possible to do this? To be explicit, given>setGeneric("sumLike",function(...,na.rm=FALSE)standardGeneric("sumLike"))>setClass("Foo",representation(a="numeric")); >aFoo <- new("Foo",a=c(1,NA)) >.sum.Foo <- function(x,na.rm) {sum(x at a,na.rm)} Then is there a setMethod call for sumLike which will despatch sumLike(aFoo,na.rm) to .sum.Foo ? If not, might this be considered a bug?> -----Original Message----- > From: Swinton, Jonathan > Sent: 19 April 2004 13:16 > To: 'r-help at stat.math.ethz.ch' > Subject: How to write an S4 method for sum or a Summary generic > > If I have a class Foo, then i can write an S3 method for sum for it: > > >setClass("Foo",representation(a="integer"));aFoo=new("Foo",a> c(1:3,NA)) > >sum.Foo <- > function(x,na.rm){print(x);print(na.rm);sum(x at a,na.rm=na.rm)} > >sum(aFoo) > > But how do I write an S4 method for this? All my attempts to > do so have foundered. For example > >setMethod("sum",signature("Foo","logical"), > function(x,na.rm){print(x);print(na.rm);sum(x at a,na.rm=na.rm)} > creates a method which seems to despatch on na.rm="Foo": > > getMethods("sum") > na.rm = "ANY": > function (..., na.rm = FALSE) > .Internal(sum(..., na.rm = na.rm)) > > na.rm = "Foo": > function (..., na.rm = FALSE) > { > .local <- function (x, na.rm) > { > print(x) > print(na.rm) > sum(x at a, na.rm = na.rm) > } > .local(..., na.rm = na.rm) > } > > na.rm = "missing": > function (..., na.rm = FALSE) > .Internal(sum(..., na.rm = na.rm)) > ##: (inherited from na.rm = "ANY") > > Pages 350-352 of the Green book discuss at some length how to > write a generic function for Summary group generics which > uses tail recursion to allow the correct method to be called > on each member of a ... argument list. But it gives no > examples of what individual method functions need to look > like. Any ideas or a place to look for working code? > > Jonathan Swinton, Statistical Scientist, Computational > Biology, Pathway Analysis, Global Sciences and Information, > AstraZeneca. >
Swinton, Jonathan
2004-May-14 16:03 UTC
[R] RE: How to write an S4 method for sum or a Summary generic
I asked a couple of weeks ago about how to write an S4 method for sum, or another member of the Summary group generics. This prompted an informed and somewhat over my head email discussion off list, but for the benefit of posterity the current answer is 1) Redefine the generic for sum as follows: ----------- setGeneric("sum", function(x, ..., na.rm = FALSE) standardGeneric("sum"),group="Summary", useAsDefault = function(x, ..., na.rm = FALSE) .Internal(sum(x, ...,na.rm = na.rm))) ----------- 2) This allows the following to work as expected ---------- setClass("Foo", representation(a="numeric")) aFoo <- new("Foo", a=c(1,NA)) setMethod("Summary", "Foo", function(x, ..., na.rm = FALSE) { cat("Foo method\n") callGeneric(x at a, ..., na.rm = na.rm) }) sum(aFoo) sum(aFoo, na.rm=TRUE) ---------- Without step 1) this does not work in R 1.9.0 but is reported to work in S-Plus 6.2. 3) Repeat for each other Summary group generic you wish to write a method for. Thanks to Brian Ripley and John Chambers for taking the time on this. Jonathan Swinton, Statistical Scientist, Computational Biology, Pathways, Global Sciences and Information, AstraZeneca, Alderley Park, Cheshire SK10 4TG UK