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.
Simply call
adder
and S3 dispatch will do the right and call the right function.You should not define the generic
adder
twice ( the call toUseMethod
).