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.

Était-ce utile?

La 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).

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top