[Rd] RE: [R] Testing for S4 objects

From: John Fox <jfox_at_mcmaster.ca>
Date: Sat 11 Dec 2004 - 14:58:15 EST


Dear r-devel list members,

I'm moving this question to r-devel because it seems thornier than I originally thought.

I've already mentioned (on r-help) that the approach that John Chambers suggested (below) fails for objects of class "by":

> x <- rnorm(100)
> y <- sample(2, 100, replace=TRUE)
> res <- by(x, y, mean)
> res

INDICES: 1
[1] -0.03429679



INDICES: 2
[1] -0.1273790
> class(res)

[1] "by"
> isS4object <- function(object)(length(attr(object, "class"))==1 &&
+ !is.null(getClass(class(object))))
> isS4object(res)

Error in getClass(class(object)) : "by" is not a defined class
>

I tried to fix that, but I've now discovered more general problems; e.g.:

> mod <- lm(y ~ x)
> class(mod)

[1] "lm"
> isS4object(mod)

[1] TRUE
> class(summary(mod))

[1] "summary.lm"
> isS4object(summary(mod))

Error in getClass(class(object)) : "summary.lm" is not a defined class
>

I've reverted to a modified version of my original proposal:

> isS4object <- function(object) {

+ !(length(object) == 1 && class(object) == "character") && length(slotNames(object)) != 0
+ }

> isS4object(res)

[1] FALSE
> isS4object(mod)

[1] FALSE
> isS4object(summary(mod))

[1] FALSE
> # example from ?mle
> x <- 0:10
> y <- c(26, 17, 13, 12, 20, 5, 9, 8, 5, 4, 8)
> ll <- function(ymax=15, xhalf=6)

+ -sum(stats::dpois(y, lambda=ymax/(1+x/xhalf), log=TRUE))
> fit <- mle(ll)

Warning message:
NaNs produced in: dpois(x, lambda, log)

> isS4object(fit)

[1] TRUE
> isS4object("mle")

[1] FALSE
>

All this is with R 2.0.1 under Windows NT.

Comments would be appreciated.

John



John Fox
Department of Sociology
McMaster University
Hamilton, Ontario
Canada L8S 4M4

905-525-9140x23604
http://socserv.mcmaster.ca/jfox

> -----Original Message-----
> From: John Chambers [mailto:johnmchambers@gmail.com]
> Sent: Tuesday, November 30, 2004 9:40 AM
> To: John Fox
> Cc: Martin Maechler; r-help@stat.math.ethz.ch
> Subject: Re: [R] Testing for S4 objects
>
> Let me suggest a different test, because slotNames was
> written to work differently when given a string or a class
> definition. With your definition,
>
> R> x <- "classRepresentation"
> R> isS4object(x)
> [1] TRUE
>
> which I assume is not what you wanted. (Given a single string,
> slotNames() tries to look up the class definition of that name.)
>
> How about the following? The logic is that an S4 object must
> have an actual class attribute of length 1 (that rules out
> basic data types, where class(x) is a string but there is no
> actual attribute, and also rules out some S3 objects). Then
> if that's true, try to look up the class definition. If it
> is non-null, seems like an S4 object.
>
> R> isS4object <- function(object)(length(attr(object, "class"))==1 &&
> + !is.null(getClass(class(object))))
> R> isS4object(x)
> [1] FALSE
> R> isS4object(getClass(class(x)))
> [1] TRUE
>
> This definition seems to work, at least on the examples I
> could think of right away. Notice though, that some classes,
> such as "ts", that have been around for a long while are
> nevertheless legitimate S4 classes, so:
>
> R> t1 = ts(1:12)
> R> isS4object(t1)
> [1] TRUE
>
> (this applies to either version of isS4object).
>
> There are a couple of details, more appropriate for the r-devel list.
> Seems a good candidate for a function to add to R.
>
>
> On Sat, 27 Nov 2004 17:48:30 -0500, John Fox <jfox@mcmaster.ca> wrote:
> > Dear Martin,
> >
> > As it turns out, the test that I proposed (i.e., testing for NULL
> > slotNames) sometimes fails. For example:
> >
> > > library(car)
> > > data(Prestige)
> > > sum <- summary(lm(prestige ~ income + education, data=Prestige))
> > > slotNames(sum)
> > character(0)
> >
> > The following, however, seems to work (at least as far as I've been
> > able to
> > ascertain):
> >
> > isS4object <- function(object) length(slotNames(object)) != 0
> >
> > I hope that this is a more robust test.
> >
> >
> >
> > John
> >
> > --------------------------------
> > John Fox
> > Department of Sociology
> > McMaster University
> > Hamilton, Ontario
> > Canada L8S 4M4
> > 905-525-9140x23604
> > http://socserv.mcmaster.ca/jfox
> > --------------------------------
> >
> > > -----Original Message-----
> > > From: Martin Maechler [mailto:maechler@stat.math.ethz.ch]
> > > Sent: Friday, November 26, 2004 3:18 AM
> > > To: John Fox
> > > Cc: r-help@stat.math.ethz.ch
> > > Subject: Re: [R] Testing for S4 objects
> > >
> > > >>>>> "JohnF" == John Fox <jfox@mcmaster.ca>
> > > >>>>> on Thu, 25 Nov 2004 22:28:50 -0500 writes:
> > >
> > > JohnF> Dear r-help list members, Is there a way to test
> > > JohnF> whether an object is an S4 object? The best that I've
> > > JohnF> been able to come up with is
> > >
> > > JohnF> isS4object <- function(object)
> > > !(is.null(slotNames(object)))
> > >
> > > you can drop one pair of "(..)" to give
> > >
> > > isS4object <- function(object) !is.null(slotNames(object))
> > >
> > >
> > > JohnF> which assumes that an S4 object has at least one
> > > JohnF> slot. I think this is safe, but perhaps I'm missing
> > > JohnF> something.
> > >
> > > The question is a very good one -- that I have posed to R-core a
> > > while ago myself.
> > >
> > > Inside utils:::str.default {which doesn't show the many
> commments
> > > in the *source* of str.default()}, I have wanted a way that even
> > > works when the 'methods' package is not attached and use the more
> > > obscure
> > >
> > > #NOT yet:if(has.class <- !is.null(cl <- class(object)))
> > > if(has.class <- !is.null(cl <- attr(object, "class")))#
> > > S3 or S4 class
> > > S4 <- !is.null(attr(cl, "package"))## <<<'kludge' FIXME!
> > > ##or length(methods::getSlots(cl)) > 0
> > >
> > > For the time being, I'd keep your function, but I don't
> think we'd
> > > guarantee that it will remain the appropriate test in all
> future.
> > > But till then many things will have happened (if not all of them
> > > ;-).
> > >
> > > Martin Maechler, ETH Zurich
> > >
> >
> > ______________________________________________
> > R-help@stat.math.ethz.ch mailing list
> > https://stat.ethz.ch/mailman/listinfo/r-help
> > PLEASE do read the posting guide!
> > http://www.R-project.org/posting-guide.html
> >



R-devel@stat.math.ethz.ch mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel Received on Sat Dec 11 15:05:20 2004

This archive was generated by hypermail 2.1.8 : Fri 18 Mar 2005 - 09:02:06 EST