Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can (should) I inherit parts of a function in R?

Tags:

oop

r

I have two functions that start pretty similarly. Hence I wonder if this is the right moment to dive into inheritance in R.

firstfunc <- function(table,pattern="^Variable") {

dframe <- get(table)
cn <- colnames(get(table))
qs <- subset(cn, cn  %in% grep(pattern, cn, value=TRUE))

    .....

}

secondfunc <- function(table,pattern="^stat"){

dframe <- get(table)
cn <- colnames(get(table))
qs <- subset(cn, cn  %in% grep(pattern, cn, value=TRUE))

    ....

}

There will be more than two functions and two patterns. My tables contains a lot of variables, which can be easily grouped by their names, which is why I use these pattern identification. It works well so far and c&p these few lines is not that much of an effort. However, is it reasonable to write these lines into one function / method and let the others inherit?

Most help I read on OO in R so far used examples that assigned attributes to data and then used generic functions. Unfortunately I did not understand yet if this can help my case too.

Thx for any suggestions, pointers to a good head first start into this!

like image 848
Matt Bannert Avatar asked Dec 01 '22 09:12

Matt Bannert


1 Answers

There is no inheritance of function parts in R. You cannot "inherit part's" of functions from other functions, only call functions from other functions. All OO paradigms in R (S3,S4,refClasses) are exactly what they say, object-oriented. Methods are dispatched according to the class of objects they receive.

Your question is really how to get rid of code repetition.

There are two ways, one standard and one not so standard.

  • Standard way: Write functions for repeated code and call them from other functions. The drawback is that functions return only one object, but you have three. So you can do something like this:

    repeated_code <- function(table, pattern){
        objects <- list()
        objects$dframe <- get(table)           
        objects$cn <- colnames(get(table))
        objects$qs <- subset(cn, cn  %in% grep(pattern, cn, value=TRUE))
        }
    
    
    firstfunc <- function(table,pattern="^Variable") {
          objects <- repeated_code(table, pattern)
          ...
          manipulate objects
          ...
          }
    
    
    secondfunc <- function(table,pattern="^Variable") {
          objects <- repeated_code(table, pattern)
          ...
          manipulate objects
          ...
          }     
    
  • Not so standard way: Use unevaluated expressions:

     redundant_code <- expression({
          dframe <- get(table)  
          cn <- colnames(get(table))
          qs <- subset(cn, cn  %in% grep(pattern, cn, value=TRUE))
     })
    
    
     firstfunc <- function(table,pattern="^Variable") {
         eval(redundant_code, envir=parent.frame())
         ...
     }
    
    
     secondfunc <- function(table,pattern="^Variable") {
         eval(redundant_code, envir=parent.frame())
         ...
     }
    

[Update: Since the R 2.12.0 there is yet another, multi-assign way. Write a function wich returns the list of objects (like in the "standard" case above). Then assign the objects in the returned list to the current evnvironmnet with list2env:

    secondfunc <- function(table,pattern="^Variable") {
          objects <- repeated_code(table, pattern)
          list2env(objects, envir = parent.frame())
          ...
          }     

]

like image 127
VitoshKa Avatar answered Dec 04 '22 11:12

VitoshKa