Using OOP and S3 methods to detect, then operate on a single vector OR all columns of a data.frame

StackOverflow https://stackoverflow.com/questions/21340966

  •  02-10-2022
  •  | 
  •  

Question

I wrote a function that operates on a single vector. Sometimes I want to use that function on whole data.frame. I can accomplish that by using sapply across the relevant variables, but now I want contain and direct the function using S3 methods.

First, the setup:

df_test <- data.frame(x = c(1, 2, 3, 4, 5), 
                      y = c(6, 7, 8, 9, 10), 
                      z = c(11, 12, 13, 14, 15))

adder <- function(x, from, to) {
  if(is.null(ncol(x))) {
    x <- structure(list(x = x, from = from, to = to), class = "single")
  } else {
    x <- structure(list(x = x, from = from, to = to), class = "multiple")
  }
  UseMethod("adder", x)
}

adder.single <- function(x, from, to) {
  x <- x + (from - to) # just some random operation here - the real function does more
  x
}

adder.multiple <- function(x, from, to) {
  x <- sapply(x, function(y) { 
    y <- structure(list(x = y, from = from, to = to), class = "single"); 
    UseMethod("adder", y) })
  x
}

So on a single vector, the function works:

> adder(df_test[,1], 2, 4)
[1] -1  0  1  2  3

But passing the entire data.frame does not:

> adder(df_test, 2, 4)
Error in from - to : 'from' is missing

It's clear to me what the problem is - adder detects that we're looking at a whole data.frame, uses the "multiple" method, which then calls the "single" method and arguments from and to are not being passed along.

I read Hadley Wickham's OOP Field Guide and Advanced Programming by Nicolas Christian, but it ain't clickin' for me. I welcome a completely different approach, as long as it uses S3 methods because part of this exercise is for me to learn how to use them.

Was it helpful?

Solution

Simply call adder and S3 dispatch will do the right and call the right function.

adder.multiple <- function(x, from, to) {
  sapply(x,  adder,from,to)
}

You should not define the generic adder twice ( the call to UseMethod).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top