Here is code that does make factor() work on a new class like yours. It uses Sv3 methods. > setClass("foo", contains="numeric") [1] "foo" > as.character.foo <- function(x) paste("x=",x@.Data,sep="") > unique.foo <- function(x, ...) structure(NextMethod("unique"), class=class(x)) > someFoo <- new("foo", c(11, 13, 11, 13, 12)) > str(factor(someFoo)) Factor w/ 3 levels "x=11","x=12",..: 1 3 1 3 2
It would be nice to have a list of methods that one needs to define for a new class in order to make it do the "basic" things you expect. Bill Dunlap Spotfire, TIBCO Software wdunlap tibco.com > -----Original Message----- > From: r-devel-boun...@r-project.org [mailto:r-devel-boun...@r-project.org] On > Behalf Of Dan Murphy > Sent: Monday, January 23, 2012 10:31 PM > To: peter dalgaard > Cc: r-devel@r-project.org > Subject: Re: [Rd] factor S4 class is NA when as.character method exists > > Thank you for your reply, Peter. But that didn't work either. Continuing > the example: > > setGeneric("unique") > setMethod("unique", "foo", function(x, incomparables = FALSE, ...){ > y <- callNextMethod(x = getDataPart(x), incomparables = incomparables, > ...) > new("foo", y) > }) > > > unique(bar) > An object of class "foo" > [1] 12 > > factor(bar) > [1] <NA> > Levels: 12 > > Indeed I had tried stepping through the 'factor' call, but perhaps in an > unsophisticated manner -- I had copied the body of 'factor' to a local > version of the function: > > myfactor <- function (x = character(), levels, labels = levels, exclude = > NA, > ordered = is.ordered(x)) > { > if (is.null(x)) ... > etc. > > And 'myfactor' worked as desired: > > > myfactor(bar) > [1] x= 12 > Levels: x= 12 > > I hypothesized that there might be a deeper interaction of an S4 > 'as.character' method with base::factor, but, having exhausted my woeful > lack of expertise, I decided to write my original email. > > Thanks for your consideration. > > Dan > > On Mon, Jan 23, 2012 at 8:25 AM, peter dalgaard <pda...@gmail.com> wrote: > > > > > On Jan 23, 2012, at 16:07 , Dan Murphy wrote: > > > > > Hello, > > > > > > 'factor' returns <NA> for my S4 object when the class is given an > > > "as.character" method. Here is a minimal example: > > > > > >> setClass("foo", contains="numeric") > > >> bar <- new("foo", 12) > > >> factor(bar) > > > [1] 12 > > > Levels: 12 > > >> setMethod("as.character", "foo", function(x) paste("x=", x@.Data)) > > > [1] "as.character" > > >> as.character(bar) > > > [1] "x= 12" > > >> factor(bar) > > > [1] <NA> > > > Levels: 12 > > > > > > I would like to 'aggregate' by my S4 objects, but 'factor' seems to be > > > getting in the way. Is there an 'as.character' implementation that works > > > better for S4 classes? I searched help.search("factor S4 class") and > > > help.search("factor S4 as.character") without success. > > > > Single-stepping the factor call would have shown you that the real problem > > is that you don't have a unique() method for your class: > > > > > unique(bar) > > [1] 12 > > > > i.e., you are getting the default numeric method, which returns a numeric > > vector, so the levels become as.character(unique(bar)) which is c("12") and > > doesn't match any of the values of as.character(bar). > > > > So, either provide a unique() method, or use factor(as.character(bar)). > > > > > > > > Thank you. > > > > > > Dan Murphy > > > > > > [[alternative HTML version deleted]] > > > > > > ______________________________________________ > > > R-devel@r-project.org mailing list > > > https://stat.ethz.ch/mailman/listinfo/r-devel > > > > -- > > Peter Dalgaard, Professor > > Center for Statistics, Copenhagen Business School > > Solbjerg Plads 3, 2000 Frederiksberg, Denmark > > Phone: (+45)38153501 > > Email: pd....@cbs.dk Priv: pda...@gmail.com > > > > > > [[alternative HTML version deleted]] > > ______________________________________________ > R-devel@r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel ______________________________________________ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel