4

This is basically the same question as Chain arithmetic operators in dplyr with %>% pipe but updated for the new (as R 4.1) pipe operator |>.

How can I chain arithmetic operators with the R native pipe |>? With dplyr/magrittr, you can use backticks for arithmetic operators, but that doesn't work with the inbuilt R pipe operator. Here's a simple example:

R.version$version.string
# [1] "R version 4.2.2 (2022-10-31 ucrt)"

x <- 2
# With dplyr/magrittr, you can use backticks for arithmetic operators
x %>% `+`(2)
# [1] 4

# But that doesn't work with the inbuilt R pipe operator
x |> `+`(2)
#  Error: function '+' not supported in RHS call of a pipe

Hopefully, the answer would be generic enough to work for any operator or in-built function that does not usually work nicely with the native R pipe (my version is R 4.2.2).

The answer https://stackoverflow.com/a/72086492/2449926 has lots of useful information on the differences between %>% and |>, but none that quite answers my question.

Tripartio
  • 1,955
  • 1
  • 24
  • 29
  • 1
    Already tried `x |> base::\`+\`(2)`? – jay.sf Apr 01 '23 at 13:06
  • @jay.sf Fantastic, this works, with backticks around the + operator. (It's hard to reproduce in the markdown here since it keeps on interpreting the backticks.) Could you please post as an answer? – Tripartio Apr 01 '23 at 13:10
  • 1
    @jay.sf your answer should be a answer! why it is important to use `base::` – TarJae Apr 01 '23 at 13:13
  • 2
    `x |> (\`+\`)(2)` should work, too. – Martin Gal Apr 01 '23 at 13:51
  • @MartinGal This works great and is very succinct. Could you please post it as an answer? – Tripartio Apr 04 '23 at 10:47
  • Maybe have a look at [What are the differences between R's new native pipe `|>` and the magrittr pipe `%>%`?](https://stackoverflow.com/questions/67633022) in section *Some functions are not supported* or [Same function but using for it the name %>% causes a different result compared when using the name :=](https://stackoverflow.com/questions/76155705). – GKi May 02 '23 at 21:51

3 Answers3

5

We can use namespace prefixing.

2 |> base::`+`(2)
# 4
jay.sf
  • 60,139
  • 8
  • 53
  • 110
2

There are two more possibilites, that are already mentioned in https://stackoverflow.com/a/72086492/12505251 :

  1. Use brackets:
2 |> (`+`)(3)
#> [1] 5
  1. Use the placeholder _ and a named argument of the binary operator:
2 |> `+`(lhs = _, 3)
#> [1] 5

Note: In the cases of + or %*% it does not seem to matter how exactly the argument is named. I guess this can be generalized to all binary operators (using R version 4.2.1).

2 |> `+`(foo = _, 3)
#> [1] 5
2 |> `+`(bar = _, 3)
#> [1] 5
2 |> `+`(lhs = _, 3)
#> [1] 5
2 |> `+`(rhs = _, 3)
#> [1] 5

c(1, 3) %*% t(c(1, 4))
c(1, 3) |> `%*%`(foo = _, t(c(1, 4)))
c(1, 3) |> `%*%`(bar = _, t(c(1, 4)))
c(1, 3) |> (`%*%`)(t(c(1, 4)))
# they all return
#>      [,1] [,2]
#> [1,]    1    4
#> [2,]    3   12

Of course, these two variants are not identical:

c(1, 3) |> `%*%`(foo = _, t(c(1, 4)))
#>      [,1] [,2]
#> [1,]    1    4
#> [2,]    3   12

c(1, 3) |> `%*%`(t(c(1, 4)), foo = _)
#>      [,1]
#> [1,]   13
Martin Gal
  • 16,640
  • 5
  • 21
  • 39
1

A workaround (though perhaps not a direct answer) would be to use an anonymous function for the desired operator:

((x + 2) * 3) / 4
#[1] 3

# Chained with anonymous functions
x |> 
  {\(x, y) x + y}(2) |> 
  {\(x, y) x * y}(3) |> 
  {\(x, y) x / y}(4)
# [1] 3

While not as elegant as magrittr's pipe

x %>%
  `+`(2) %>%
  `*`(3) %>%
  `/`(4)
# [1] 3

this workaround at least allows for chaining.

Tripartio
  • 1,955
  • 1
  • 24
  • 29