1

I have a vector vec like this vec <- c(1,4,5) and I want to check whether there are any steps down in the vector. I do this using:

any(diff(vec) < 0)
# [1] FALSE

No steps down. Okay. But when I try to use this code in a pipe I get a TRUE and an warning:

library(magrittr)
vec %>% diff() %>% any(. < 0)
# [1] TRUE
# Warning message:
# In any(., . < 0) : coercing argument of type 'double' to logical

How to correctly write any(diff(vec) < 0) as a pipe?

LulY
  • 976
  • 1
  • 9
  • 24
  • See: [What are the differences and use cases of the five Magrittr Pipes %>%, %<>%, %$%, %!>% and %T>%?](https://stackoverflow.com/questions/76326742) at *When dot is nested, lhs is still placed first* – GKi Jun 26 '23 at 13:27

4 Answers4

2

You can try

vec %>%
    diff() %>%
    `<`(0) %>%
    any()

or

vec %>%
    diff() %>%
    {
        . < 0
    } %>%
    any()

or

vec %>%
    {
        any(diff(.) < 0)
    }
ThomasIsCoding
  • 96,636
  • 9
  • 24
  • 81
2

You have a couple of solutions already, but no explanation. The reason your original didn't work is that magrittr pipes treat . differently when it is in a nested function call.

By nested function call, I mean that . is not an argument to the function that is the target of the pipe. In any(. < 0), that function is any(), and its argument is . < 0, which is actually a function call to the < function. So the . is in a "nested function call".

If . is only in a nested function call, it is implicitly used as the first argument as well, so the code

x %>% any(. < 0)

is treated as

any(x, x < 0)

To suppress this weird behaviour, put the expression in braces, i.e. your example would be

vec %>% diff() %>% { any(. < 0) }
user2554330
  • 37,248
  • 4
  • 43
  • 90
1

using magrittr pipes:

vec %>% diff() %>% `<`(0) %>% any()
[1] FALSE

Using base pipes:

vec |> diff() |> {\(x)x < 0}() |> any()
[1] FALSE

See here for more info: https://stackoverflow.com/a/72474832/16730940

Paul Stafford Allen
  • 1,840
  • 1
  • 5
  • 16
1

Base

vec |> diff() |> base::`<`(0) |> any()
# [1] FALSE

magrittr

library(magrittr)

vec %>% diff %>% `<`(0) %>% any
# [1] FALSE

or, as suggested by @MrFlick

library(magrittr)

vec %>% diff %>% is_less_than(0) %>% any
# [1] FALSE

Data:

vec <- c(1, 4, 5)
jay.sf
  • 60,139
  • 8
  • 53
  • 110
  • 1
    If you import all of `magrittr`, might as well use `vec %>% diff %>% is_less_than(0) %>% any` to make things clearer. – MrFlick Jun 26 '23 at 13:50
  • @MrFlick Thanks for sharing your magrittr knowledge, I've included it! – jay.sf Jun 28 '23 at 07:11