我应该避免使用管道操作员编程包吗?

时间:2016-08-10 17:52:23

标签: r magrittr

当我在R中对程序包进行编程时,是否有任何客观原因可以避免R magrittr中的pipe operators,例如%>%

更具体地说,我想知道使用管道运算符是否会导致编码冲突或(正面或负面)影响性能。我正在寻找这类案件的具体具体例子。

3 个答案:

答案 0 :(得分:32)

与R中编写的所有高级函数一样,%>%会带来很多开销,因此不要在循环中使用它(这包括隐式循环,例如*apply系列,或者每个组在dplyrdata.table等包中循环。这是一个例子:

library(magrittr)
x = 1:10

system.time({for(i in 1:1e5) identity(x)})
#   user  system elapsed 
#   0.07    0.00    0.08 
system.time({for(i in 1:1e5) x %>% identity})
#   user  system elapsed 
#  15.39    0.00   16.68 

答案 1 :(得分:18)

不应过于轻易地将依赖项添加到程序包中。一般而言,程序包所依赖的每个程序包都会在依赖项更新时进行维护,或者在依赖项停止时被维护。它还使人们(稍微)更难以安装您的软件包 - 尽管在互联网连接不可靠的情况下才会显着增加。但是如果有人想把你的软件包放在拇指驱动器上安装某个地方,他们还需要确保他们拥有你所有的依赖项(以及依赖项的依赖项......)。

Base R和默认包具有很长的历史,R-Core非常清楚不会引入会破坏下游依赖关系的更改。 magrittr更新,看起来像2014年2月首次登陆CRAN。

实际上,magrittr一直稳定,似乎是一种低风险依赖。特别是如果你只导入%>%并忽略它提供的更深奥的运算符(如dplyrtidyr等),你可能非常安全。它的受欢迎程度几乎可以保证,即使它的创建者放弃它,也会有人接管维护。

答案 2 :(得分:7)

管道范例与标准功能编程"相比,颠倒了功能应用的明显顺序。这是否具有不良后果取决于功能符号学(我最初的错误定义是“语义学”,但是spielchucker虽然我的意思是semiotics,但似乎没问题)。我碰巧认为管道创建的代码可读性较差,但这是因为我已经训练了我的大脑来查看来自"由内到外"的编码。比较:

 y <- func3 ( func2( func1( x) ) )

 y <- x %>% func1 %>% func2 %>% func3

以我的思维方式,第一个更具可读性,因为信息&#34;流动&#34;向外(并始终向左)并最终位于最左边的位置y,其中第二个中的信息向右流动然后&#34;转向并向左发送。管道范例还允许无参数函数应用程序,我认为这会增加错误的可能性。仅使用位置参数匹配的R编程通常会产生完全不可思议的错误消息,而惩罚自己始终(或几乎总是)使用参数名称可以获得更多信息性错误消息。

我倾向于采用具有一致方向的管道范例:

 y <- func3 %<% func2 %<% func1 %<% x
 # Or
 x %>% func1 %>% func2 %>% func3 -> y

而且我认为这实际上是pkg原始设计的一部分 - magrittr我相信其中包括一个“左管道”。以及“右管道”。所以这可能是一个人为因素设计问题。 R具有左右相关性,dplyr / magrittr管道范例的典型用户通常遵循该规则。我可能患有僵硬脑综合征,所有年轻人都可能是未来,所以你做出了选择。我真的很佩服Hadley合理化数据输入和处理的目标,以便将文件和SQL服务器视为通用串行设备。

David Robinson提供的例子表明,跟踪争论是一个大问题,我完全同意。我通常的方法是使用制表符和空格来突出显示层次结构:

func3 ( func2( 
           func1(x, a),    # think we need an extra comma here
               b, c),       # and here
        d, e, f) 

x %>% func1(a) %>% func2(b, c) %>% func3(d, e, f)

不可否认,在检查缺少的逗号或括号时,使用语法感知编辑器可以更轻松地实现这一点,但在上面的示例中,没有使用逗号或者括号,堆叠/间距方法确实突出了我认为的语法错误。 (当遇到困难时,我也会迅速添加参数名称,但我认为这同样适用于管道代码策略。)