15

For single argument functions, it is reasonably trivial to translate "standard" R code to the magrittr pipe style.

mean(rnorm(100))

becomes

rnorm(100) %>% mean

For multi-argument functions, it isn't clear to me what the best way to proceed is. There are two cases.

Firstly, the case when additional arguments are constants. In this case, you can create an anonymous function which changes the constant values. For example:

mean(rnorm(100), trim = 0.5)

becomes

rnorm(100) %>% (function(x) mean(x, trim = 0.5))

Secondly, the case where multiple vector arguments are required. In this case, you can combine inputs into a list, and create an anonymous function that operates on list elements.

cor(rnorm(100), runif(100))

becomes

list(x = rnorm(100), y = runif(100)) %>% (function(l) with(l, cor(x, y)))  

In both cases my solutions seem clunky enough that I feel like I'm missing a better way to do this. How should I pipe multiple arguments to functions?

Tim Goodman
  • 23,308
  • 7
  • 64
  • 83
Richie Cotton
  • 118,240
  • 47
  • 247
  • 360

3 Answers3

11

In v. 1.5 there are two options:

list(x = rnorm(100), y = runif(100)) %$% cor(x, y) 

Which is essemtially the same as

list(x = rnorm(100), y = runif(100)) %>% with(cor(x, y)) # you could also do this earlier  

Or

list(x = rnorm(100), y = runif(100)) %>% { cor(.$x, .$y) } 

The { pair creates a lambda (unary function) on the fly so you don't have to do the whole (function(x) { ... }) thing.

As a side note, the inset and inset2 aliases can be used to "pick up" values in a pipeline, in e.g. lists.

Stefan
  • 1,835
  • 13
  • 20
  • Oh my god, you have no idea how long I have been wishing there was a shorter syntax for anonymous functions in R... – Patrick B. Apr 21 '17 at 03:35
8

Using the pipeR package the solution for the cor-example would be:

pipeR:

set.seed(123)
rnorm(100) %>>% cor(runif(100))

[1] 0.05564807

margrittr:

set.seed(123)
rnorm(100) %>% cor(y = runif(100))

[1] 0.05564807

There is an excellent pipeR tutorial available from the autor of the package. There's not much of a difference in this case :-)

hvollmeier
  • 2,956
  • 1
  • 12
  • 17
2

The first problem can be solved by %>%'s clever evaluation. The clunky solution simplifies to

rnorm(100) %>% mean(trim = 0.5)

The second problem can be simplified in a similar way, though it isn't clear if this is the "best" solution.

rnorm(100) %>% cor(y = runif(100))
Richie Cotton
  • 118,240
  • 47
  • 247
  • 360
  • 1
    I tendto look to `pipeR` in cases like this. It's partly what idiom each user is more comfortable with, so I recommend folks play around with both packages for a while to see which helps them more. – Carl Witthoft Sep 21 '14 at 13:16
  • 1
    @CarlWitthoft Interesting. So how does a `pipeR` solution look? – Richie Cotton Sep 21 '14 at 13:24
  • 1
    Well, I'm not expert at either pipe tool yet, but what I like about `pipeR` is that you can use a "." in multiple places on the right-hand side to represent the output of the left-hand side. – Carl Witthoft Sep 21 '14 at 16:47