用于 ! (或任何逻辑运算符)%>%(magrittr)会产生意外输出

时间:2016-06-09 17:42:14

标签: r magrittr

我遇到%>%!结合时会产生非常惊人的输出的情况。请考虑以下代码:

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

好的,没什么好惊的。但如果我尝试使用%>%来缩短它,那就会发生奇怪的事情:

!is.na(x) %>% sum

[1] TRUE

TRUE?不是我的预期 - 它应该是20

如果我删除了!,它会按预期提供0

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

如果我添加括号,它可以工作:

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

并将!视为一种功能:

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

!is.na(x) %>% sum做什么,为什么返回TRUE而不是20

编辑:其他逻辑运算符产生类似的行为:

> T&T %>% sum()
[1] TRUE
> {T&T} %>% sum()
[1] 1

> T|T %>% sum()
[1] TRUE
> {T|T} %>% sum()
[1] 1

3 个答案:

答案 0 :(得分:6)

我怀疑这是一个操作顺序问题:

!is.na(x) %>% sum

正在评估

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

相当于TRUE

答案 1 :(得分:4)

虽然我接受了@ C-Z_的回答,但我想添加另一个来提供上下文。感谢@rawr指导我?Syntax

基本上%>%被认为是一个运算符,如%in%,因此它必须遵守操作的顺序。在Syntax帮助页面上,这对应于%any%运算符(即任何中缀运算符),因为用户可以随意定义这些运算符。碰巧,这意味着%>%在任何逻辑运算符之前以及算术运算符(例如*\)之前触发。因此,如果你天真地像我一样,认为%>%的左侧将在链中的下一步之前完成,你可以得到一些惊喜。例如:

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

不执行3+2=5, 5*4= 20, 20/2=10

取而代之的是2*4/2=4, 4+3=7,因为%>%优先于+

如果您使用magrittr包中的功能,例如:

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

按预期得到10。在3+2周围放置括号也会为您10

在我的原始示例中,逻辑运算符(例如!)的优先级低于%>%,因此它们在总和竞争之后最后一次执行。

故事的道德:小心地将%>%与其他运营商混合。

答案 2 :(得分:1)

你也可以使用&#34; not&#34;来自magrittr包的别名:

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

[1] 20