s-news
[Top] [All Lists]

Re: class and inheritance

To: "Russell Ivory" <Russell.Ivory@MerrickBank.com>
Subject: Re: class and inheritance
From: Tim Hesterberg <timh@insightful.com>
Date: 2 Feb 2007 17:28:44 -0800
Cc: <s-news@lists.biostat.wustl.edu>
In-reply-to: <C8D9459E0E12A04D9CD897043F52F74903F461AE@MBCEXCHANGE.MBC.com> (Russell.Ivory@MerrickBank.com)
References: <C8D9459E0E12A04D9CD897043F52F74903F461AE@MBCEXCHANGE.MBC.com>
Some ideas:

* Use as.matrix to convert the data frame to a matrix
        cor(as.matrix(testdata))
  It would be nice if this works for your object, but I'd be surprised.

* Modify numerical.matrix or as.matrix.data.frame to handle your object.

* Switch to S3 objects.

If you create your object as 
  (ordinary vector or matrix) + attributes + S3 class
then things may just work.  That is one big difference between S3
objects and S4 objects -- most functions in S+ work as-is for S3
objects, but you have to write methods for S4 objects.

For example, compare the 
        S3 class "bs" (created by bs(), inherits from "basis"), 
to the 
        S4 class "timeSeries" (inherits from "series" and "seriesVirtual")


methods(class = "bs")
# only predict.bs
methods(class = "basis")
# only "[.basis" "print.basis"

There are very few methods -- you don't need more.  Functions like
mean, ncol, ... work without additional effort.


In contrast, for S4 objects you need to write a large number of
methods to make many functions work with the object:

> names(getMethodsForClass("timeSeries"))
[1] "splus plot timeSeries"        "splus trellisPlot timeSeries"
[3] "splus deltat timeSeries"     
> names(getMethodsForClass("series"))
[1] "splus density series"   "splus seriesLag series"
> names(getMethodsForClass("seriesVirtual"))
 [1] "splus Math seriesVirtual"                    
 [2] "splus Math2 seriesVirtual"                   
 [3] "splus Ops seriesVirtual"                     
 [4] "splus Ops seriesVirtual#missing"             
 [5] "splus Ops ANY#seriesVirtual"                 
 [6] "splus Ops seriesVirtual#seriesVirtual"       
 [7] "splus [ seriesVirtual"                       
 [8] "splus [<- seriesVirtual#vector"              
 [9] "splus [<- seriesVirtual#seriesVirtual"       
[10] "splus apply seriesVirtual"                   
[11] "splus coerce seriesVirtual#numeric"          
[12] "splus coerce seriesVirtual#complex"          
[13] "splus coerce seriesVirtual#character"        
[14] "splus coerce seriesVirtual#matrix"           
[15] "splus coerce seriesVirtual#logical"          
[16] "splus coerce seriesVirtual#integer"          
[17] "splus coerce seriesVirtual#vector"           
[18] "splus colMaxs seriesVirtual"                 
[19] "splus colMeans seriesVirtual"                
[20] "splus colMedians seriesVirtual"              
[21] "splus colMins seriesVirtual"                 
[22] "splus colProds seriesVirtual"                
[23] "splus colQuantiles seriesVirtual"            
[24] "splus colRanges seriesVirtual"               
[25] "splus colSums seriesVirtual"                 
[26] "splus colVars seriesVirtual"                 
[27] "splus density seriesVirtual"                 
[28] "splus dim seriesVirtual"                     
[29] "splus duplicated seriesVirtual"              
[30] "splus format seriesVirtual"                  
[31] "splus is.na seriesVirtual"                   
[32] "splus mean seriesVirtual"                    
[33] "splus median seriesVirtual"                  
[34] "splus nrow seriesVirtual"                    
[35] "splus numRows<- seriesVirtual"               
[36] "splus rowMaxs seriesVirtual"                 
[37] "splus rowMeans seriesVirtual"                
[38] "splus rowMins seriesVirtual"                 
[39] "splus rowRanges seriesVirtual"               
[40] "splus rowSums seriesVirtual"                 
[41] "splus rowVars seriesVirtual"                 
[42] "splus sample seriesVirtual"                  
[43] "splus show seriesVirtual"                    
[44] "splus which.na seriesVirtual"                
[45] "splus length seriesVirtual"                  
[46] "splus concat.two seriesVirtual#seriesVirtual"
[47] "splus summary seriesVirtual"                 
[48] "splus Summary seriesVirtual"                 
[49] "splus quantile seriesVirtual"      "splus sort seriesVirtual"         
[51] "splus sort.list seriesVirtual"     "splus cor seriesVirtual"          
[53] "splus cor ANY#seriesVirtual"       "splus var seriesVirtual"          
[55] "splus var ANY#seriesVirtual"       "splus diff seriesVirtual"         
[57] "splus subscript2d seriesVirtual"   "splus subscript2d<- seriesVirtual"
[59] "splus numRows seriesVirtual"       "splus ncol seriesVirtual"         
[61] "splus numCols seriesVirtual"       "splus seriesLength seriesVirtual" 
[63] "splus numCols<- seriesVirtual"     "splus rowIds seriesVirtual"       
[65] "splus colIds seriesVirtual"        "splus rowIds<- seriesVirtual"     
[67] "splus colIds<- seriesVirtual"      "splus start seriesVirtual"        
[69] "splus end seriesVirtual"           "splus shift seriesVirtual"        
[71] "splus aggregate seriesVirtual"     "splus units seriesVirtual"        
[73] "splus deltat seriesVirtual"        "splus frequency seriesVirtual"    
[75] "splus window seriesVirtual"        "splus pairs seriesVirtual"        
[77] "splus boxplot seriesVirtual"      

And for functions like numerical.matrix, you can't write a method,
so you'd have to modify the function itself.

I talk more about S3 and S4 classes in the Advanced Programming class,
        Advanced Programming in S-PLUS: 
                30 Apr - 1 May UK, 7-8 May CH, 9-10 May FR
                17-18 May Philadelphia
        http://www.insightful.com/services/training.asp

getMethodsForClass is my own function, below.

========================================================
| Tim Hesterberg       Senior Research Scientist       |
| timh@insightful.com  Insightful Corp.                |
| (206)802-2319        1700 Westlake Ave. N, Suite 500 |
| (206)283-8691 (fax)  Seattle, WA 98109-3044, U.S.A.  |
|                      www.insightful.com/Hesterberg   |
========================================================


> getMethodsForClass
function(Class)
{
  # Return a list containing S4 methods for a class.
  # Like methods(class="foo"), but for S4 methods.
  # e.g. getMethodsForClass("seriesVirtual")
  result <- list()
  for(i in search()) {
    if(!exists("Generics", meta = 1, where = i))
      next
    gen <- get("Generics", meta = 1, where = i)
    for(g in gen) {
      if(!exists(paste("M#", g, sep = ""), meta = 1, where = i))
        next
      #
      meths <- getMethods(f = g, where = i)
      w <- (Class == meths@signatures$sigs)
      if(!any(w))
        next
      # Use one of three methods, depending what is defined
      # First requires library(resample).  Second requires S+7.0 or later.
      if(exists("fastColSums")) w <- fastColSums(w, n = length(meths@signatures$
          args)) > 0 else if(is.element("n", names(colSums.default)))
        w <- colSums(w, n = length(meths@signatures$args)) > 0
      else {
        w <- matrix(w, nrow = length(meths@signatures$args))
        w <- colSums(w, n = length(meths@signatures$args)) > 0
      }
      definitions <- meths@definitions[w]
      names(definitions) <- paste(i, g, meths@signatures$signames[w])
      result <- c(result, definitions)
    }
  }
  result
}

Tim Hesterberg


>Hi S list.
>
>I need to define a new class for credit bureau data so that I can create
>new methods for dealing with special missing codes, etc. If I assign the
>new class to each vector, and then make a data frame out of these new
>class vectors, all seems to work well.  However, if I assign columns of
>a data frame to the new class (cb.data) after the data frame exists,
>things blow up. For example, I cannot get a correlation matrix as
>follows:
>(I'm using S-Plus 7.0 Professional Developer)
> 
>#Creating both integer and numeric data vectors and a data frame
>> test1 <- c(4, 6, 5, 7, 5, 4, 5, 3, 5)
>> test2 <- c(21, 65, 54, 87, 65, 32, 21, 54, 87)
>> test3 <- rnorm(9, 12, 3)
>> testdata <- data.frame(cbind(test1, test2, test3))
>
> 
>#Define a new class "cb.data":
>> setClass("cb.data", "numeric")
>      # At least the way I understand it, class cb.data extends class
>       # numeric, i.e. it is a prototype of and inherits all that
>       # numeric has to offer.
>       # But knowing some data may be integer, I instruct that as well:
>
>> setIs("cb.data", "integer")
>
>
>#getClass shows that cb.data extends both integer and numeric:
>> getClass("cb.data")
>
>No slots; prototype of class "numeric"
>
>Extends:
>Class "integer" by direct inclusion
>Class "numeric" by direct inclusion
>Class "vector" indirectly through class "numeric"
>Class "positionsNumeric" indirectly through class "numeric"
>Class "complex" indirectly through class "numeric"
>Class "positions" indirectly through class "positionsNumeric"
>
>
>#Now I assign the class to each column:
>> for(i in 1:3)
>          class(testdata[, i]) <- "cb.data"
>
>
>#Correlations seem to be complex, if I read the output correctly
>> cor(testdata[, 1], testdata[, 2])
>[1] 0.5611317+0i
>> cor(testdata[, 1], testdata[, 3])
>[1] -0.08105978+0i
>
> 
>#And I get an error trying to create the correlation matrix:
>> cor(testdata)
>Problem in numerical.matrix(x): Non-atomic (list) variables are not
>allowed 
>Use traceback() to see the call stack
>
>
>
>Any suggestions are greatly appreciated.
>
>Russell Ivory | AVP Modeling Manager | Merrick Bank | (801) 545-6640 |
>russell.ivory@merrickbank.com
>
>10705 South Jordan Gateway
>Suite 200
>South Jordan, UT 84095
>****************************************************************************This
> e-mail and any files transmitted with it are confidential and are intended 
>solely for the use of the individual or entity to whom it is addressed. If you 
>are not the intended recipient or the person responsible for delivering the 
>e-mail to the intended recipient, be advised that you have received this 
>e-mail in error, and that any use, dissemination, forwarding, printing, or 
>copying of this e-mail is strictly prohibited. If you received this e-mail in 
>error, please return the e-mail to the sender at Merrick Bank and delete it 
>from your computer. Although Merrick Bank attempts to sweep e-mail and 
>attachments for viruses, it does not guarantee that either are virus-free and 
>accepts no liability for any damage sustained as a result of viruses.


<Prev in Thread] Current Thread [Next in Thread>