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

From: John Chambers <jmc_at_r-project.org>
Date: Tue, 24 Jan 2012 15:05:20 -0800

On 1/24/12 9:35 AM, Prof Brian Ripley 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.

Creating a simple generic version of unique() (not just "some other function...") causes S4 method selection to work for code that has access to that function, but calls from within the base namespace will still see the S3 version.

The safest technique is to ensure that both S4 and S3 dispatch see the same method.



setClass("myFactor", contains = "factor")

setGeneric("unique")

unique.myFactor <- function (x, incomparables = FALSE, ...)

     unique(as.character(x))

setMethod("unique", "myFactor", unique.myFactor)


With this in PkgA and suitable exports from the namespace:

> library(PkgA)
> methods("unique")

[1] unique.POSIXlt         unique.array           unique.data.frame
[4] unique.default         unique.matrix          unique.myFactor
[7] unique.numeric_version

> showMethods("unique")

Function: unique (package base)
x="ANY"
x="myFactor"

Someday there may be a more natural approach.

John

>
>> > 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] 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
>>>>
>>>> --
>>>> 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
>>
>> ______________________________________________
>> R-devel_at_r-project.org mailing list
>> https://stat.ethz.ch/mailman/listinfo/r-devel
>
>



R-devel_at_r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel Received on Tue 24 Jan 2012 - 23:07:43 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 - 04:50:11 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