Using! (or any logical operator) with%>% (magrittr) produces unexpected output

I am faced with a situation where %>% produces a very surprising output combined with ! . Consider the following code:

 x <- c(1:20) y <- !is.na(x) > y [1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE > sum(Y) [1] 20 

Well, there is nothing surprising. But if I try to shorten it using %>% , a strange thing will happen:

 !is.na(x) %>% sum [1] TRUE 

TRUE ?? Not what I expected - it should be 20 .

If I remove ! , it will give me 0 , as expected:

 > is.na(x) %>% sum [1] 0 

and if I add brackets, it works:

 > {!is.na(x)} %>% sum [1] 20 

and processing ! how the function works:

 > is.na(x) %>% `!` %>% sum [1] 20 

What does !is.na(x) %>% sum , and why does it return TRUE , not 20 ?

EDIT: Other logical operators produce similar behavior:

 > T&T %>% sum() [1] TRUE > {T&T} %>% sum() [1] 1 > T|T %>% sum() [1] TRUE > {T|T} %>% sum() [1] 1 
+6
source share
3 answers

I suspect this is the order of operations:

 !is.na(x) %>% sum 

appreciates

 !(is.na(x) %>% sum) 

Which is equivalent to TRUE

+6
source

Although I accepted the @ C-Z_ answer, I want to add another to provide context. Thanks @rawr for pointing me to ?Syntax .

In general, %>% is considered an operator, for example, %in% , and as such it must obey the order of operations. On the Syntax help page, this corresponds to the %any% operator (i.e., any infix operator), since users can define them as they wish. As this happens, this means that %>% triggered before any logical operator, as well as before arithmetic operators (for example, * and \ ). As a result, if you are naive, like me, that the left side of %>% ends before the next step in the chain, you may get some surprises. For instance:

 3+2 %>% '*'(4) %>% `/`(2) 

Does not 3+2=5, 5*4= 20, 20/2=10

instead, it does 2*4/2=4, 4+3=7 , since %>% takes precedence over + .

If you use functions in the magrittr package, for example:

 add(3,2) %>% multiply_by(4) %>% divide_by(2) 

You get 10 as expected. Placing brackets around 3+2 will also give you 10 .

In my initial examples, logical operators such as ! , have a lower priority than %>% , so they act last after the amount has competed.

The moral of the story: be careful when mixing %>% with other operators.

+4
source

You can also use the alias "not" from the magrittr package:

 > is.na(1:20) %>% not %>% sum 

[1] 20

+1
source

All Articles