【问题标题】:What are the differences between R's new native pipe `|>` and the magrittr pipe `%>%`?R 的新原生管道 `|>` 和 magrittr 管道 `%>%` 有什么区别?
【发布时间】:2021-08-10 10:53:40
【问题描述】:

在 R 4.1 中引入了本地管道运算符,它比以前的实现“更精简”。我已经注意到原生 |> 和 magrittr 管道 %>% 之间的一个区别,即 2 %>% sqrt 有效,但 2 |> sqrt 无效,必须写为 2 |> sqrt()。使用新的管道操作符时是否还有更多的差异和陷阱需要注意?

【问题讨论】:

  • 您查看过?pipeOp 和?"%>%" hep 页面了吗?这是一个很好的信息来源。

标签: r pipe tidyverse


【解决方案1】:

两者之间的另一个区别是. 的管道输入值可以用作magrittr 管道中的占位符

c("dogs", "cats", "rats") %>% grepl("at", .)
#[1] FALSE  TRUE  TRUE

但这对于 R 的原生管道是不可能的。

c("dogs", "cats", "rats") |> grepl("at", .)

grepl(c("dogs", "cats", "rats"), "at", .) 中的错误:对象 '.'没找到

这里有不同的引用方式-

  1. 写一个单独的函数-
find_at = function(x) grepl("at", x)
c("dogs", "cats", "rats") |> find_at()
#[1] FALSE  TRUE  TRUE

2 一个。使用匿名函数 -

c("dogs", "cats", "rats") |> {function(x) grepl("at", x)}()

2 乙。使用 new 匿名函数语法

c("dogs", "cats", "rats") |> {\(x) grepl("at", x)}()
  1. 按名称指定第一个参数。这依赖于本机管道管道进入第一个 unnamed 参数的事实,因此如果您为第一个参数提供名称,它会“溢出”到第二个参数(如果您指定多个参数,依此类推按名称参数)
c("dogs", "cats", "rats") |> grepl(pattern="at")
#> [1] FALSE  TRUE  TRUE

示例 1 和 2 取自 - https://www.jumpingrivers.com/blog/new-features-r410-pipe-anonymous-functions/

示例 3 取自 https://mobile.twitter.com/rlangtip/status/1409904500157161477

【讨论】:

  • 亲爱的 Shah Ronak,当我使用本机基础 R 管道时,我的 Rstudio 引发了一个意外的令牌符号,我想知道您是否知道可能导致这种情况的原因。
  • 你安装了 R 4.1 吗?
  • 是的,我已经更新了我的 Rstudio 到最新版本。
  • 这很奇怪。你在 Windows 上吗?您是否也将代码复制粘贴到 R 中?尝试手动写下来。
  • 是的,你是对的!这很奇怪。不,我根本不复制粘贴,但我不明白为什么代码运行没有任何问题,而意外的标志仍然存在。
【解决方案2】:

本机管道是作为语法转换实现的,因此2 |> sqrt() 与sqrt(2) 相比没有明显的开销,而2 %>% sqrt() 有一点点损失。

microbenchmark(sqrt(1), 
               2 |> sqrt(), 
               3 %>% sqrt())
# Unit: nanoseconds
#          expr  min     lq    mean median   uq   max neval
#       sqrt(1)  117  126.5  141.66  132.0  139   246   100
#       sqrt(2)  118  129.0  156.16  134.0  145  1792   100
#  3 %>% sqrt() 2695 2762.5 2945.26 2811.5 2855 13736   100

您会看到传递给microbenchmark 的表达式2 |> sqrt() 如何被解析为sqrt(2)。这也可以在

中看到
quote(2 |> sqrt())
# sqrt(2)

【讨论】:

    【解决方案3】:

    R 4.1.0 中添加的基本 R 管道 |>“只是”进行功能组合。 IE。我们可以看到它的使用真的和函数调用是一样的:

    > 1:5 |> sum()             # simple use of |>
    [1] 15
    > deparse(substitute( 1:5 |> sum() ))
    [1] "sum(1:5)"
    > 
    

    这有一些后果:

    • 它让它更快一点
    • 它使它更简单、更健壮
    • 它使限制性更强:sum() 这里需要括号才能正确调用
    • 它限制了“隐式”数据参数的使用

    这导致可能使用当前“可用但未激活”的=>(您需要为此设置环境变量_R_USE_PIPEBIND_,并且对于R 4.2.0 可能会更改)。

    (最初是作为对复制此 over here 的问题的回答而提供的,我只是按照建议将其复制了。)

    编辑: 随着关于“=> 是什么”的后续问题出现,这里有一个快速跟进。 请注意,此运算符可能会发生变化。

    > Sys.setenv("_R_USE_PIPEBIND_"=TRUE)
    > mtcars |> subset(cyl == 4) |> d => lm(mpg ~ disp, data = d)
    
    Call:
    lm(formula = mpg ~ disp, data = subset(mtcars, cyl == 4))
    
    Coefficients:
    (Intercept)         disp  
         40.872       -0.135  
    
    > deparse(substitute(mtcars |> subset(cyl==4) |> d => lm(mpg ~ disp, data = d)))
    [1] "lm(mpg ~ disp, data = subset(mtcars, cyl == 4))"
    > 
    

    deparse(substitute(...)) 在这里特别好。

    【讨论】:

    • 隐式数据参数是来自 magrittr 的 .?可能使用=> 是什么意思? pipebind 会像%<>%吗?
    • 是的。有一些使用=> 将数据元素显式 分配给命名变量的示例,例如x,并在lm(...., data=x) 中使用它。
    • 我仍然不确定=> 做了什么,但我想这是一个单独的问题。
    • 没错。而且也是暂时的。但我会快速编辑一下。
    猜你喜欢
    • 2018-08-25
    • 2018-04-29
    • 2021-05-08
    • 2020-03-07
    • 2013-09-05
    • 2020-03-21
    • 2015-02-02
    • 2010-09-16
    相关资源
    最近更新 更多