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