我遇到%>%
与!
结合时会产生非常惊人的输出的情况。请考虑以下代码:
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
答案 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