5

Let's say I have a tibble (or data frame, whatever) with a list of function names. Let's say, something like:

functions <- tibble(c("log()", "log10()", "sqrt()"))

I want to be able to pipe a data set to one of these functions, chosen by index. For example, I might want to do something like:

data %>% functions[[1]]

But I can't seem to get it to work. I'm very new to pipes, but I am pretty sure this is easy, even if can't get it to work with !! etc.

Thanks in advance.

Mooks
  • 593
  • 4
  • 12

3 Answers3

6

1) match.fun Use match.fun to turn a string into a function. The dot, ., is optional.

functions <- c("log", "log10", "sqrt")
10 %>% match.fun(functions[2])(.)
## [1] 1

1a) This could also be written as:

10 %>% (match.fun(functions[2]))
## [1] 1

1b) or

10 %>% (functions[2] %>% match.fun)
## [1] 1

2) do.call do.call would also work:

10 %>% { do.call(functions[2], list(.)) }
## [1] 1

3) call/eval Generally eval is frowned upon but it does form another alternative:

10 %>% call(functions[2], .) %>% eval
## [1] 1
G. Grothendieck
  • 254,981
  • 17
  • 203
  • 341
4

In addition to the answers already given it is worth noting, that you can store pretty much anything in R lists, even functions. So this works as well:

funs <- list(log, log10, sqrt)
f <- funs[[1]]
2 %>% f
Jannik Buhr
  • 1,788
  • 2
  • 11
  • 11
3

You can do this :

functions <- c("log", "log10", "sqrt")

there's no reason to put those in a tibble, and if you do you'll need functions[[1]][1] as @ Aaghaz-Hussain mentions.

seq(10) %>% get(functions[1])()
# [1] 0.0000000 0.6931472 1.0986123 1.3862944 1.6094379 1.7917595 1.9459101 2.0794415 2.1972246 2.3025851

get will retrieve the function definition from its name as a string, after this it's a straightforward pipe, except you need to make sure the () are explicit as seq(10) %>% get(functions[[1]]) it will be interpreted as seq(10) %>% get(.,functions[[1]])

moodymudskipper
  • 46,417
  • 11
  • 121
  • 167