3

This has come up in multiple instances, and I do not know if this current instance is generalizable to the many cases where this arises for me, but I'm hoping an answer may shed some light.

The simplest version of this is when I am doing some data processing and want to perform an evaluation on the result of a pipe. A simple example would be:

> seq(9) %>% > 4
Error: unexpected '>' in "seq(9) %>% >"
> seq(9) %>% . > 4
Error in .(.) : could not find function "."

The desired output would be a logical vector

FALSE FALSE FALSE FALSE TRUE TRUE TRUE TRUE TRUE

In many circumstances I want to evaluate on some piped output but have to assign it and then perform the evaluation for it to work:

seq(9) -> vec
vec > 4

Is there a way to complete these sorts of evaluations within a pipe chain entirely?

Brandon
  • 1,722
  • 1
  • 19
  • 32
  • 2
    `sapply` is unnecessary, `>` is vectorized – Ben Bolker Nov 09 '17 at 18:19
  • @BenBolker Oh right, good call. – Mako212 Nov 09 '17 at 18:21
  • Some very related questions, might be good to create an R-FAQ: [Numeric calculations using `dplyr`'s piping command](https://stackoverflow.com/q/46836185/903061), [Order of operations with piping](https://stackoverflow.com/q/38531508/903061). I know I've seen others too. They don't quite seem like duplicates, but a canonical duplicate could probably be constructed. – Gregor Thomas Nov 09 '17 at 18:26

4 Answers4

6

You need to use curly braces if you just want to use pipes.

seq(9) %>% {. > 4}

[1] FALSE FALSE FALSE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE

I'd recommend using purrr if you're going to be piping these kinds of things, as it will result in a bit more readable code.

library(purrr)

map_lgl(seq(9), ~.x > 4)

[1] FALSE FALSE FALSE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE
Jake Kaupp
  • 7,892
  • 2
  • 26
  • 36
  • 1
    I know it's a weird example, but it is a little laughable to describe `map_lgl(seq(9), ~.x > 4)` as "more readable" than the unpiped alternative, `seq(9) > 4`. – Gregor Thomas Nov 09 '17 at 18:28
  • I see your point, but I meant in the context of a longer chain of code. I just find the use of braces in the middle of a chain a bit jarring. – Jake Kaupp Nov 09 '17 at 18:32
5

One more option is to call the > function as a function rather than an operator:

> seq(9) %>% `>`(4)
[1] FALSE FALSE FALSE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE
> seq(9) %>% '>'(4)
[1] FALSE FALSE FALSE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE

I think the backquotes make the most sense, but regular quotes do work in this case as well.

Greg Snow
  • 48,497
  • 6
  • 83
  • 110
4

magrittr provides "aliases" to turn binary operators into pipe-able functions. I don't care for them myself, but you can do

library(magrittr)
seq(9) %>% is_greater_than(4)

See the full list at ?add (which is an alias for +). There are implementations for everything from + to [[.

Gregor Thomas
  • 136,190
  • 20
  • 167
  • 294
2

In a slightly broader context, this is easily done with mutate:

library(dplyr)
data_frame(x=1:9) %>% mutate(big_x = x>4)

Unsolicited opinion: If you're mostly working with atomic vectors, I suspect that the tidyverse/piping approach is going to be more trouble than it's worth. As the other answer suggests, you can use purrr, but again, base R may work perfectly well. More context for your problem might help.

Ben Bolker
  • 211,554
  • 25
  • 370
  • 453
  • My work are very often are actually matrices and as far as I can tell I can't use dplyr commands (ie mutate, etc) without converting into a data frame. I had searched for a way but it doesn't appear that functionality exists without converting into a data frame. – Brandon Nov 09 '17 at 23:31