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

本秂侑毒 提交于 2020-01-11 08:46:06

问题


I have run across a situation where %>% produces very surprising output when 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

Ok, nothing surprising there. But if I try to shorten it using %>% weird stuff happens:

!is.na(x) %>% sum

[1] TRUE

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

If I remove the ! it gives me 0 as expected:

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

and if I add brackets it works:

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

and treating ! as a function works:

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

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

EDIT: The 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

回答1:


I suspect that it's an order of operations issue:

!is.na(x) %>% sum

is evaluating to

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

Which is equivalent to TRUE




回答2:


Although I accepted @C-Z_ 's answer I want to add another to provide context on this. Thanks to @rawr for directing me to ?Syntax.

Basically %>% is considered to be an operator, like %in% and as such it has to obey the order of operations. On the Syntax help page this corresponds to the %any% operator (i.e. any infix operator), as users can define these at will. As it happens, this means that %>% fires before any logical operator and also before arithmetic operators (e.g. * and \). As a result, if you are naively, like I was, thinking that the left side of %>% will complete before the next step in the chain, you can get some surprises. For example:

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

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

instead it does 2*4/2=4, 4+3=7, because the %>% has precedence over +.

If you use the functions in the magrittr package such as:

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

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

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

Moral of the story: Be careful mixing %>% with other operators.




回答3:


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

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

[1] 20



来源:https://stackoverflow.com/questions/37732820/use-of-or-any-logical-operator-with-magrittr-produces-unexpected-outpu

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