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.
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.