[Rd] How to put my S4 class into data.frame

Martin Maechler maechler at stat.math.ethz.ch
Sat Nov 4 10:42:37 CET 2006


>>>>> "Gregor" == Gregor Gorjanc <gregor.gorjanc at bfro.uni-lj.si>
>>>>>     on Sat, 04 Nov 2006 02:09:13 +0100 writes:

    Gregor> Ferdinand Alimadhi wrote:

      >> tmp$comp <- x at ratios ?!

    Gregor> I "lose" class here and that is not what I
    Gregor> want. Perhaps I should stick with list instead of
    Gregor> data.frame.

Yes, I probably would, at least for the time being.

OTOH, it's interesting that some methods to "stick some S4
objects into a data frame do work fine , at least for the
following case (R-script below) -- and I wonder if we (R developers)
shouldn't think about more explicitly supporting this,
e.g., by stating something like

 >>  If an S4 object simply *contains* an atomic class that can be
 >>  used as data.frame column, then that S4 object can also be used
 >>  as data.frame column

and trying to fix all cases where the above is not fulfilled.


  setClass("Real", contains="numeric")
  (r <- new("Real", pi * 1:3))
  try( dd <- data.frame(x = 1:3, R = r) ) ## fails
  ## Error in as.data.frame.default(x[[i]], optional = TRUE) :
  ## 	cannot coerce class "Real" into a data.frame

  dd <- data.frame(x = 1:3)
  dd[,"R"] <- r ## works fine .. didn't I say just yesterday how much
		## I recommend [, <name>] indexing for data frames ?
  dd
  str(dd)
  dd[1:2,]
  ## but
  str(dd[1:2,]) # has lost the class -- of course since r[1:2] loses it
  ## -> you need to define a correct subset method for your class
  ## e.g.,
  setMethod("[", signature(x = "Real", i = "ANY"),
	    function(x, i,j,drop, ...) new("Real", callNextMethod()))

  r[1:2] # now correct
  str(dd[1:2,]) # correct too


Martin Maechler, ETH Zurich

    >> Gregor Gorjanc wrote:
    >> 
    >>> Hello!
    >>> 
    >>> I am developing a composition class, which represents a
    >>> composition of mixture of levels, say soil has three
    >>> components and each component accounts for 1/3 of the
    >>> unit. I have tried with S4 class system and I would
    >>> appreciate any help here. I was hoping that I would be
    >>> able to include instance of my class into a
    >>> data.frame. However, I encounter problems.
    >>> 
    >>> Simple definition of class could be
    >>> 
    >>> setClass(Class="composition",
    >>> representation=representation(ratios="matrix"))
    >>> 
    >>> n <- 2 k <- 3
    >>> 
    >>> x <- new(Class="composition",
    >>> ratios=matrix(data=rep(x=1/3, times=n*k), nrow=n,
    >>> ncol=k))
    >>> 
    >>> x An object of class "composition" Slot "ratios": [,1]
    >>> [,2] [,3] [1,] 0.3333333 0.3333333 0.3333333 [2,]
    >>> 0.3333333 0.3333333 0.3333333
    >>> 
    >>> tmp <- data.frame(id=1:2) tmp$comp <- x Error: object is
    >>> not subsettable
    >>> 
    >>> As I understand this, my problem is that x is of length
    >>> 1 as the following works
    >>> 
    >>> tmp$comp <- c(x, x)
    >>> 
    >>> although I am not able to print tmp now
    >>> 
    >>> tmp Error in unlist(x, recursive, use.names) : argument
    >>> not a list
    >>> 
    >>> but this is expected as I (probably) need show/print
    >>> method for this.  How can I put my class into data.frame
    >>> or how can I make my class behave as a vector?
    >>> 
    >>> Thanks!

    Gregor> -- Lep pozdrav / With regards, Gregor Gorjanc
    Gregor> ----------------------------------------------------------------------
    Gregor> University of Ljubljana PhD student Biotechnical
    Gregor> Faculty Zootechnical Department URI:
    Gregor> http://www.bfro.uni-lj.si/MR/ggorjan Groblje 3 mail:
    Gregor> gregor.gorjanc <at> bfro.uni-lj.si

    Gregor> SI-1230 Domzale tel: +386 (0)1 72 17 861 Slovenia,
    Gregor> Europe fax: +386 (0)1 72 17 888



More information about the R-devel mailing list