我遇到过这样一种情况:%>%
与!
组合时会产生非常惊人的输出。考虑以下代码:
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
将CCD_ 8作为一个函数处理:
> 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
我怀疑这是操作顺序问题:
!is.na(x) %>% sum
正在评估
!(is.na(x) %>% sum)
相当于TRUE
虽然我接受了@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
。
在我最初的例子中,逻辑运算符(如!
)的优先级低于%>%
,因此它们在和竞争之后最后起作用。
故事寓意:小心将%>%
与其他运算符混合。
您也可以使用magrittr包中的"not"别名:
> is.na(1:20) %>% not %>% sum
[1] 20