48

I would like to understand why, in the the dplyr or magrittr package, and more specifically the chaining function %>% has some trouble with the basic operators +, -, *, and /

Chaining takes the output of previous statement and feeds it as first argument of the next:

1:10 %>% sum
# [55]

Thus how come this doesn't work

1:10 %>%  *2 %>% sum
1:10 %>% .*2 %>% sum

I also found that the following syntax works for adding/substracting, but not multiply or divide. why so?

1:10 %>% +(2) # works OK
1:10 %>% *(2) # nope...

So should I write an anonymous function even to do a *2 operation on my data.frame?

1:10 %>% (function(x) x*2) %>% sum

Thanks, I couldn't find the answer in other SO questions.

agenis
  • 8,069
  • 5
  • 53
  • 102
  • 6
    You want to use the `magrittr` package here instead of dplyr. dplyr is only for working with data.frames while the pipe operator (`%>%`) is originally from magrittr. – talat Dec 08 '14 at 18:26
  • 2
    Just add them normally? – stanekam Jan 23 '15 at 02:31
  • 4
    Explanation of this behaviour: plus and minus only work here because the parser sees them as unary plus and minus operators, as in `-2`. So its valid syntax. So it parses okay here, and then magrittr gets to work mangling the evaluation into a binary `"-"(x, 2)` expression. There's no unary '*' or '/' function, so those ops fail. Once quoted, they become valid syntax again and the corresponding function is gotten. – Spacedman Jan 23 '15 at 14:27
  • Eventually I add that this way of doing also works for test operators such as '>', '=='. – agenis Mar 07 '16 at 22:54

4 Answers4

66

Surround the operators with backticks or quotes, and things should work as expected:

1:10 %>%  `*`(2) %>% sum
# [1] 110

1:10 %>%  `/`(2) %>% sum
# [1] 27.5
jbaums
  • 27,115
  • 5
  • 79
  • 119
  • 11
    Better to use backticks to quote, because it more clearly distinguishes between non-syntactic function names and strings. (The fact that `"+"(1, 3)` works is, in my opinion, a historical artefact. – hadley Dec 08 '14 at 22:11
48

Or use the Aliases in magrittr package, e.g.:

1:10 %>% multiply_by(2)
# [1]  2  4  6  8 10 12 14 16 18 20

1:10 %>% add(2)
# [1]  3  4  5  6  7  8  9 10 11 12

The Aliases include 'words' for boolean operators, extract/replace, and arithmetic operators

Henrik
  • 65,555
  • 14
  • 143
  • 159
3

Thought I'd share the magrittr documentation so you could see all of your options!

Currently implemented aliases are...

extract `[`
extract2    `[[`
inset   `[<-`
inset2  `[[<-`
use_series  `$`
add `+`
subtract    `-`
multiply_by `*`
raise_to_power  `^`
multiply_by_matrix  `%*%`
divide_by   `/`
divide_by_int   `%/%`
mod `%%`
is_in   `%in%`
and `&`
or  `|`
equals  `==`
is_greater_than `>`
is_weakly_greater_than  `>=`
is_less_than    `<`
is_weakly_less_than `<=`
not (`n'est pas`)   `!`
set_colnames    `colnames<-`
set_rownames    `rownames<-`
set_names   `names<-`
set_class   `class<-`
set_attributes  `attributes<-`
set_attr    `attr<-`
1

As an addition to the answer above, it is handy to use Aliases in magrittr package, e.g.:

magrittr's pipeable operator replacements

operator functional alternative
x * y x %>% multiply_by(y)
x ^ y x %>% raise_to_power(y)
x[y] x %>% extract(y)
Hamzah
  • 8,175
  • 3
  • 19
  • 43