Re: [Rd] factor S4 class is NA when as.character method exists

From: Dan Murphy <chiefmurphy_at_gmail.com>
Date: Wed, 25 Jan 2012 07:22:04 -0800

But my NA issue does not arise from the S3 generic 'unique' alone but from the interaction of that S3 generic with the non-S3 generic 'as.character' (R.methodsS3::isGenericS3.default("as.character") returns FALSE). Here is Bill's code with his S3 as.character foo method replaced by my S4.

> setClass("foo", contains="numeric")
[1] "foo"
> setMethod("as.character", "foo", function(x) paste("x=", x@.Data))
[1] "as.character"
> 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 "11","12","13": NA NA NA NA NA

I thought I remember reading at some point in the past that package developers were encouraged to implement methods in S4 rather than S3 because ... S3 support would dissipate? I can't remember the details. ...

In any event, this example suggests that I should first implement methods in S3 if possible because that approach is more robust, at least as measured by potential S3 pitfalls. I have no problems with that.

Thanks for the hints.

On Tue, Jan 24, 2012 at 9:35 AM, Prof Brian Ripley <ripley_at_stats.ox.ac.uk>wrote:

> On 24/01/2012 17:17, William Dunlap wrote:
>
>> Here is code that does make factor() work on a new
>> class like yours. It uses Sv3 methods.
>>
>
> Which is necessary as unique() is an S3 generic in the base namespace, and
> creating some other function named 'unique' elsewhere (which is what
> setGeneric does) is ineffective.
>
>
> > 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.
>>
>
> It would be nice to have a list of such things ... I suspect they depend
> more heavily on the value of 'you' than the class.
>
>
> Bill Dunlap
>> Spotfire, TIBCO Software
>> wdunlap tibco.com
>>
>> -----Original Message-----
>>> From: r-devel-bounces_at_r-project.org [mailto:r-devel-bounces_at_r-**
>>> project.org <r-devel-bounces_at_r-project.org>] On Behalf Of Dan Murphy
>>> Sent: Monday, January 23, 2012 10:31 PM
>>> To: peter dalgaard
>>> Cc: r-devel_at_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<pdalgd_at_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_at_r-project.org mailing list
>>>>>
https://stat.ethz.ch/mailman/**listinfo/r-devel<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.mes_at_cbs.dk Priv: PDalgd_at_gmail.com
>>>>
>>>>
>>>>
>>> [[alternative HTML version deleted]]
>>>
>>> ______________________________**________________
>>> R-devel_at_r-project.org mailing list
>>> https://stat.ethz.ch/mailman/**listinfo/r-devel<https://stat.ethz.ch/mailman/listinfo/r-devel>
>>>
>>
>> ______________________________**________________
>> R-devel_at_r-project.org mailing list
>> https://stat.ethz.ch/mailman/**listinfo/r-devel<https://stat.ethz.ch/mailman/listinfo/r-devel>
>>
>
>
> --
> Brian D. Ripley, ripley_at_stats.ox.ac.uk
> Professor of Applied Statistics, http://www.stats.ox.ac.uk/~**ripley/<http://www.stats.ox.ac.uk/~ripley/>
> University of Oxford, Tel: +44 1865 272861 (self)
> 1 South Parks Road, +44 1865 272866 (PA)
> Oxford OX1 3TG, UK Fax: +44 1865 272595
>

        [[alternative HTML version deleted]]



R-devel_at_r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel Received on Wed 25 Jan 2012 - 15:25:00 GMT

This quarter's messages: by month, or sorted: [ by date ] [ by thread ] [ by subject ] [ by author ]

All messages

Archive maintained by Robert King, hosted by the discipline of statistics at the University of Newcastle, Australia.
Archive generated by hypermail 2.2.0, at Wed 25 Jan 2012 - 21:20:12 GMT.

Mailing list information is available at https://stat.ethz.ch/mailman/listinfo/r-devel. Please read the posting guide before posting to the list.

list of date sections of archive