piping a vector into all() to test equality

那年仲夏 提交于 2020-04-30 10:38:08

问题


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.


回答1:


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.



来源:https://stackoverflow.com/questions/60106626/piping-a-vector-into-all-to-test-equality

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!