Skip to content

How to put my class into data.frame

8 messages · Ferdinand Alimadhi, Martin Maechler, Gregor Gorjanc +2 more

#
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!
#
tmp$comp <- x at ratios   ?!
Gregor Gorjanc wrote:

            

  
    
#
Ferdinand Alimadhi wrote:
I "lose" class here and that is not what I want. Perhaps I should stick
with list instead of data.frame.

  
    
#

        
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
#
Hi,
Martin Maechler wrote:
OK. Why do you say "at least for the time being"? Are there any plans to
generalize putting S4 classes that are not atomic into data.frame?
Gregor
#
There are also many cases where using a list as a data.frame column
will cause errors, depending on the contents of the list.

Hadley
#
John Chambers wrote:
As far as I see this (at the risk of uterly simplifying the issue) new
data.frame (perhaps dataFrame) could just be a list? of classes that
have the same length i.e. length() should have the same value.

Gregor