Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

piping a vector into all() to test equality

I'm trying to pipe a vector into an all() statement to check if all elements are equal to a certain value. I figure I need to use the exposition pipe %$% since all() does not have a built-in data argument. My attempt leads to an error:

library(tidyverse)
library(magrittr)

vec <- c("a", "b", "a")

vec %>%
  keep(!grepl("b", .)) %$%
  all(. == "a")
#> Error in eval(substitute(expr), data, enclos = parent.frame()): invalid 'envir' argument of type 'character'

If I break the pipe before all() and assign the output to an object p, and then pass p to all() as a second command it works fine:

vec %>%
  keep(!grepl("b", .)) -> p

all(p == "a")
#> [1] TRUE

I don't understand why this works while my first attempt does not. I'd like to be able to do this in a single pipe that results in TRUE.

If vec is instead a tibble the following works:

vec <- tibble(var = c("a", "b", "a"))

vec %>%
  filter(!grepl("b", var)) %$%
  all(.$var == "a")
#> [1] TRUE

This doesn't suit my purposes as well, and I'd for my own understanding to know why my first attempt does not work.

like image 516
lost Avatar asked Dec 15 '25 03:12

lost


1 Answers

The way pipe works is it takes the left-hand side of the pipe operator and passes it as a first argument to the right hand side function. So here, in this case as we need to modify the data argument to all , we need to stop pipe from passing the LHS to the RHS. We can do that by using {}.

library(magrittr)

vec %>% purrr::keep(!grepl("b", .)) %>% {all(. == 'a')}
#[1] TRUE

In vec , let's check if all the elements are either "a" or "b". We can use %in% here.

vec <- c("a", "b", "a")

Plain version without pipes would be :

all(vec %in% c('a', 'b'))
#[1] TRUE

With pipes, if we try

vec %>% all(. %in% c('a', 'b'))

We get

#[1] NA

Warning message: In all(., . %in% c("a", "b")) : coercing argument of type 'character' to logical

what is happening here is

all(vec, vec %in% c('a', 'b'))
#[1] NA

Warning message: In all(vec, vec %in% c("a", "b")) : coercing argument of type 'character' to logical

which returns the same message.

To avoid this we use {}

vec %>% {all(. %in% c('a', 'b'))}
#[1] TRUE

which gives us the expected answer.

like image 107
Ronak Shah Avatar answered Dec 16 '25 18:12

Ronak Shah



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!