R 的原生管道 `|>` 和 magrittr 管道 `%>%` 有什么区别?

2023-12-26

在 R 4.1(2021 年 5 月)中,引入了原生管道运算符,它比以前的实现“更精简”。我已经注意到本地人之间的一个区别|>和马格里特管%>%,即2 %>% sqrt有效但是2 |> sqrt没有并且必须写成2 |> sqrt()。使用本机管道运算符时是否还有更多差异和陷阱需要注意?


Topic Magrittr 2.0.3 Base 4.3.0
Operator %>% %<>% %$% %!>% %T>% |> (since 4.1.0)
Function call 1:3 %>% sum() 1:3 |> sum()
  1:3 %>% sum Needs brackets / parentheses
  1:3 %>% `+`(4) Some functions are not supported
Insert on first empty place mtcars %>% lm(formula = mpg ~ disp) mtcars |> lm(formula = mpg ~ disp)
Placeholder . _ (since 4.2.0)
  mtcars %>% lm(mpg ~ disp, data = . ) mtcars |> lm(mpg ~ disp, data = _ )
  mtcars %>% lm(mpg ~ disp, . ) Needs named argument
  1:3 %>% setNames(., .) Can only appear once
  1:3 %>% {sum(sqrt(.))} Nested calls are not allowed
Extraction call mtcars %>% .$cyl
mtcars %>% {.$cyl[[3]]} or
mtcars %$% cyl[[3]]
mtcars |> _$cyl (since 4.3.0)
mtcars |> _$cyl[[3]]

Environment %>% has additional function environment
use:"x" %!>% assign(1)
"x" |> assign(1)
Create Function top6 <- . %>% sort() %>% tail() Not possible
Speed Slower because Overhead of function call Faster because Syntax transformation

使用时许多差异和限制就会消失|>与(匿名)函数结合使用:
1 |> (\(.) .)()
-3:3 |> (\(.) sum(2*abs(.) - 3*.^2))()

另请看一下:如何纯粹在基础 R 中进行管道传输(“基础管道”)? https://stackoverflow.com/questions/65329335 and 五种 Magrittr 管道 %>%、%%、%$%、%!>% 和 %T>% 的区别和用例是什么? https://stackoverflow.com/questions/76326742.


需要括号

library(magrittr)

1:3 |> sum
#Error: The pipe operator requires a function call as RHS

1:3 |> sum()
#[1] 6

1:3 |> approxfun(1:3, 4:6)()
#[1] 4 5 6

1:3 %>% sum
#[1] 6

1:3 %>% sum()
#[1] 6

1:3 %>% approxfun(1:3, 4:6)  #But in this case empty parentheses are needed
#Error in if (is.na(method)) stop("invalid interpolation method") :
1:3 %>% approxfun(1:3, 4:6)()
#[1] 4 5 6

Some 功能 are not 支持的 https://github.com/wch/r-source/blob/e3b297a64f932d402dc59727c088386cae6a8112/src/main/names.c#L1007, 但有些仍然可以通过将它们放在括号中来调用,通过函数调用它们::,使用占位符,在函数中调用它或定义函数的链接。

1:3 |> `+`(4)
#Error: function '+' not supported in RHS call of a pipe

1:3 |> (`+`)(4)
#[1] 5 6 7

1:3 |> base::`+`(4)
#[1] 5 6 7

1:3 |>  `+`(4, e2 = _)
#[1] 5 6 7

1 |> (`+`)(2) |> (`*`)(3) #(1 + 2) * 3  or `*`(`+`(1, 2), 3) and NOT 1 + 2 * 3
#[1] 9

1:3 |> (\(.) . + 4)()
#[1] 5 6 7

fun <- `+`
1:3 |> fun(4)
#[1] 5 6 7

1:3 %>% `+`(4)
#[1] 5 6 7

占位符需要命名参数

2 |> setdiff(1:3, _)
#Error: pipe placeholder can only be used as a named argument

2 |> setdiff(1:3, y = _)
#[1] 1 3

2 |> (\(.) setdiff(1:3, .))()
#[1] 1 3

2 %>% setdiff(1:3, .)
#[1] 1 3

2 %>% setdiff(1:3, y = .)
#[1] 1 3

也适用于可变参数函数...(dot-dot-dot) 参数,占位符_需要用作命名参数。

"b" |>  paste("a", _, "c")
#Error: pipe placeholder can only be used as a named argument

"b" |>  paste("a", . = _, "c")
#[1] "a b c"

"b" |>  (\(.) paste("a", ., "c"))()
#[1] "a b c"

占位符可以只出现一次

1:3 |> setNames(nm = _)
#1 2 3 
#1 2 3 

1:3 |> setNames(object = _, nm = _)
#Error in setNames(object = "_", nm = "_") : 
#  pipe placeholder may only appear once

1:3 |> (\(.) setNames(., .))()
#1 2 3 
#1 2 3 

1:3 |> list() |> setNames(".") |> with(setNames(., .))
#1 2 3 
#1 2 3 

1:3 |> list(. = _) |> with(setNames(., .))
#1 2 3
#1 2 3

1:3 %>% setNames(object = ., nm = .)
#1 2 3
#1 2 3

1:3 %>% setNames(., .)
#1 2 3 
#1 2 3

嵌套调用不允许

1:3 |> sum(sqrt(x=_))
#Error in sum(1:3, sqrt(x = "_")) : invalid use of pipe placeholder

1:3 |> (\(.) sum(sqrt(.)))()
#[1] 4.146264

1:3 %>% {sum(sqrt(.))}
#[1] 4.146264

提取呼叫
自 4.3.0 起的实验性功能。占位符_现在也可以用于前向管道的右侧|>表达式作为提取调用中的第一个参数,例如_$coef。更一般地,它可以用作提取链的头部,例如_$coef[[2]]*

mtcars |> _$cyl
mtcars |> _[["cyl"]]
mtcars |> _[,"cyl"]
# [1] 6 6 4 6 8 6 8 4 4 6 6 8 8 8 8 8 8 4 4 4 4 8 8 8 8 4 4 4 8 6 8 4

mtcars |> _$cyl[[4]]
#[1] 6

mtcars %>% .$cyl
mtcars %>% .[["cyl"]]
mtcars %>% .[,"cyl"]
# [1] 6 6 4 6 8 6 8 4 4 6 6 8 8 8 8 8 8 4 4 4 4 8 8 8 8 4 4 4 8 6 8 4

#mtcars %>% .$cyl[4] #gives mtcars[[4]]
mtcars %>% .$cyl %>% .[4]
#[1] 6

No 附加环境

assign("x", 1)
x
#[1] 1

"x" |> assign(2)
x
#[1] 2

"x" |> (\(x) assign(x, 3))()
x
#[1] 2

1:3 |> assign("x", value=_)
x
#[1] 1 2 3

"x" %>% assign(4)
x
#[1] 1 2 3

4 %>% assign("x", .)
x
#[1] 1 2 3

"x" %!>% assign(4) #Use instead the eager pipe
x
#[1] 4

5 %!>% assign("x", .)
x
#[1] 5

创建一个函数

top6 <- . %>% sort() %>% tail()
top6(c(1:10,10:1))
#[1]  8  8  9  9 10 10

其他可能性:
不同的管道操作符和不同的占位符可以通过以下方式实现奇异烟斗 ->.;什么不是管道(参见缺点 https://stackoverflow.com/q/67868289/10488504) 正在覆盖.

1:3 ->.; sum(.)
#[1] 6

mtcars ->.; .$cyl
# [1] 6 6 4 6 8 6 8 4 4 6 6 8 8 8 8 8 8 4 4 4 4 8 8 8 8 4 4 4 8 6 8 4

mtcars ->.; .$cyl[4]
#[1] 6

1:3 ->.; setNames(., .)
#1 2 3 
#1 2 3 

1:3 ->.; sum(sqrt(x=.))
#[1] 4.146264

"x" ->.; assign(., 5)
x
#[1] 5

6 ->.; assign("x", .)
x
#[1] 6

1:3 ->.; . + 4
#[1] 5 6 7

1 ->.; (`+`)(., 2) ->.; (`*`)(., 3)
#[1] 9

1 ->.; .+2 ->.; .*3
#[1] 9

并且评价不同。

x <- data.frame(a=0)
f1 <- \(x) {message("IN 1"); x$b <- 1; message("OUT 1"); x}
f2 <- \(x) {message("IN 2"); x$c <- 2; message("OUT 2"); x}

x ->.; f1(.) ->.; f2(.)
#IN 1
#OUT 1
#IN 2
#OUT 2
#  a b c
#1 0 1 2

x |> f1() |> f2()
#IN 2
#IN 1
#OUT 1
#OUT 2
#  a b c
#1 0 1 2

f2(f1(x))
#IN 2
#IN 1
#OUT 1
#OUT 2
#  a b c
#1 0 1 2

或者定义一个自定义管道运算符这是设置.到新环境中的左旋值(lhs)的值并评估其中的右旋值(rhs)。但这里无法创建或更改调用环境中的值。

`:=` <- \(lhs, rhs) eval(substitute(rhs), list(. = lhs))

mtcars := .$cyl[4]
#[1] 6

1:3 := setNames(., .)
#1 2 3 
#1 2 3 

1:3 := sum(sqrt(x=.))
#[1] 4.146264

"x" := assign(., 6)
x
#Error: object 'x' not found

1 := .+2 := .*3
#[1] 9

所以另一个尝试是将 lhs 分配给占位符.在调用环境中并评估调用环境中的 rhs。但在这儿.如果它已经存在,将从调用环境中删除。

`?` <- \(lhs, rhs) {
  on.exit(if(exists(".", parent.frame())) rm(., envir = parent.frame()))
  assign(".", lhs, envir=parent.frame())
  eval.parent(substitute(rhs))
}

mtcars ? .$cyl[4]
#[1] 6

1:3 ? setNames(., .)
#1 2 3 
#1 2 3 

1:3 ? sum(sqrt(x=.))
#[1] 4.146264

"x" ? assign(., 6)
x
#[1] 6

1 ? .+2 ? .*3
#[1] 9

另一种可能性是更换所有.与 lhs 以便在评估期间.不再作为名称存在。

`%|>%` <- \(lhs, rhs)
  eval.parent(eval(call('substitute', substitute(rhs), list(. = lhs))))

mtcars %|>% .$cyl[4]
[1] 6

1:3 %|>% setNames(., .)
1 2 3 
1 2 3

1:3 %|>% sum(sqrt(x=.))
[1] 4.146264

"x" %|>% assign(., 6)
x
#[1] 6

1 %|>% .+2 %|>% .*3
#[1] 7

所使用的运算符的名称会影响运算符的优先级:请参阅相同的函数,但使用名称 %>% 会导致与使用名称 := 时不同的结果 https://stackoverflow.com/questions/76155705.
有关更高级的选项,请参阅:编写自己的/自定义的管道运算符 https://stackoverflow.com/questions/76160601.


Speed

library(magrittr)

`:=` <- \(lhs, rhs) eval(substitute(rhs), list(. = lhs))

`?` <- \(lhs, rhs) {
  on.exit(if(exists(".", parent.frame())) rm(., envir = parent.frame()))
  assign(".", lhs, envir=parent.frame())
  eval.parent(substitute(rhs))
}

`%|>%` <- \(lhs, rhs)
  eval.parent(eval(call('substitute', substitute(rhs), list(. = lhs))))


x <- 42
bench::mark(min_time = 0.2, max_iterations = 1e8
, x
, identity(x)
, "|>" = x |> identity()
, "|> _" = x |> identity(x=_)
, "->.;" = {x ->.; identity(.)}
, "|> f()" = x |> (\(y) identity(y))()
, "%>%" = x %>% identity
, ":=" = x := identity(.)
, "list." = x |> list() |> setNames(".") |> with(identity(.))
, "%|>%" = x %|>% identity(.)
, "?" = x ? identity(.)
)

Result

   expression       min   median `itr/sec` mem_alloc `gc/sec`   n_itr  n_gc
   <bch:expr>  <bch:tm> <bch:tm>     <dbl> <bch:byt>    <dbl>   <int> <dbl>
 1 x            31.08ns   48.2ns 19741120.        0B     7.46 2646587     1
 2 identity(x) 491.04ns 553.09ns  1750116.        0B    27.0   323575     5
 3 |>          497.91ns 548.08ns  1758553.        0B    27.3   322408     5
 4 |> _        506.87ns 568.92ns  1720374.        0B    26.9   320003     5
 5 ->.;        725.03ns 786.04ns  1238488.        0B    21.2   233864     4
 6 |> f()      972.07ns   1.03µs   929926.        0B    37.8   172288     7
 7 %>%           2.76µs   3.05µs   315448.        0B    37.2    59361     7
 8 :=            3.02µs   3.35µs   288025.        0B    37.0    54561     7
 9 list.         5.19µs   5.89µs   166721.        0B    36.8    31752     7
10 %|>%          6.01µs   6.86µs   143294.        0B    37.0    27076     7
11 ?             30.9µs  32.79µs    30074.        0B    31.3     5768     6
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

R 的原生管道 `|>` 和 magrittr 管道 `%>%` 有什么区别? 的相关文章

  • R 脚本自动化时的不同结果

    以下命令对 pdf 文件执行 Ghostscript 这pdf file变量包含该 pdf 的路径 bbox lt system paste C gs gs8 64 bin gswin32c exe sDEVICE bbox dNOPAUS
  • .wav 文件长度/持续时间,无需读入文件

    有没有办法提取有关 wav 文件长度 持续时间的信息 而无需在 R 中读取文件 我有数千个这样的文件 如果我必须阅读每个文件才能找到其持续时间 那将需要很长时间 Windows 文件资源管理器为您提供了打开 长度 字段的选项 并且您可以查看
  • numpy.histogram 的 hist 维度,密度 = True

    假设我有这个数组 A array 0 0019879 0 00172861 0 00527226 0 00639585 0 00242005 0 00717373 0 00371651 0 00164218 0 00034572 0 008
  • kableExtra 中的 row_spec() 函数不会在 html 输出中创建水平线

    我想在 kableextra 表中的某一行下方添加一条水平线 row spec 函数的参数 hline after 应该在行下方添加水平线 row spec 文档 https www rdocumentation org packages
  • 在 R 中创建一个运行计数变量?

    我有一个足球比赛结果的数据集 我希望通过创建一组类似于世界足球 Elo 公式的运行评级来学习 R 我遇到了麻烦 在 Excel 中看似简单的事情在 R 中并不完全直观 例如 4270 个观察中的前 15 个具有必要的变量 date t 1
  • 计算每个唯一值出现的次数

    假设我有 v rep c 1 2 2 2 25 现在 我想计算每个唯一值出现的次数 unique v 返回唯一值是什么 但不返回它们的数量 gt unique v 1 1 2 我想要一些能给我的东西 length v v 1 1 25 le
  • R中的一元加/减是什么?

    来自 R 的详细信息部分Syntax http stat ethz ch R manual R patched library base html Syntax html帮助页面 定义了以下一元和二元运算符 他们被列出 在优先级组中 从最高
  • 如何删除箱线图上的刻度线

    我试图从箱线图中删除 x 轴刻度线 但保留与刻度线关联的标签 这在基础 R 中可能吗 colors lt c lightskyblue3 gray78 gold1 wheat1 boxplot avgscore module data mi
  • R - Plm 和 lm - 固定效应

    我有一个平衡面板数据集 df 本质上由三个变量组成 A B and Y 对于一堆独特识别的区域来说 它会随着时间的推移而变化 我想运行一个回归 其中包括区域 下面等式中的区域 和时间 年份 固定效应 如果我没记错的话 我可以通过不同的方式来
  • 使用 pracma::findpeaks 识别持续峰值

    我的语法有问题peakpat内的选项findpeaks内的函数pramcaR 包 v 2 1 1 我使用的是 R 3 4 3 x64 Windows 我希望该函数能够识别可能有两个重复值的峰值 并且我相信该选项peakpat这就是我能做到的
  • 通过间接引用列来修改数据框中的某些值

    我正在整理一些数据 我们将失败的数据分类到垃圾箱中 并按批次计算每个分类箱的有限产量 我有一个描述排序箱的元表 这些行按升序测试顺序排列 一些排序标签带有非语法名称 sort tbl lt tibble tribble weight lab
  • 绘制点之间的所有线

    我有以下 R 代码 x lt c 0 01848598 0 08052353 0 06741172 0 11652034 y lt c 0 4177541 0 4042247 0 3964025 0 4074685 d lt data fr
  • Dendextend:关于如何根据定义的组为树状图的标签着色

    我正在尝试使用一个名为 dendextend 的很棒的 R 包来绘制树状图并根据一组先前定义的组为其分支和标签着色 我已阅读您在 Stack Overflow 中的答案以及 dendextend vignette 的常见问题解答 但我仍然不
  • 尝试读取 CSV 文件时出现“无法识别的字符串转义”

    我正在尝试导入一个 csv文件 以便我可以观看此视频 R ggplot2 图形直方图 http www youtube com watch v 47kWynt3b6M 我安装了所有正确的软件包 包括ggplot以及相关的包 视频中的第一个说
  • API 请求和curl::curl_fetch_memory(url, handle = handle) 中的错误:SSL 证书问题:证书已过期

    几天前 我运行了代码几个月 没有任何问题 GET url myurl query 今天我遇到一个错误 Error in curl curl fetch memory url handle handle SSL certificate pro
  • 在 R 中创建虚拟变量,排除某些情况为 NA

    我的数据看起来像这样 V1 V2 A 0 B 1 C 2 D 3 E 4 F 5 G 9 我想创建一个虚拟变量R where 0 1 1 2 3 4 and NA 0 5 9 应该很简单 有人可以帮忙吗 我们可以转换V2 into a fa
  • 在 R 中使用 lapply 绘制多个数据帧

    我正在尝试使用 lapply 函数绘制多个数据帧 每个数据帧一个图 但是尽管有关此主题的所有帖子我都找不到答案 因为我不断收到错误 图的输出列表为空 我的数据结构如下 df1 lt mtcars gt group by cyl gt tal
  • 使用 Shiny 发布平行坐标图表时出现“错误:路径[1]="”:没有这样的文件或目录”

    我有一个似乎很常见但我还没有找到解决方案的问题 当尝试使用 rCharts Parcoords 发布 Web 应用程序时 出现以下错误 错误 路径 1 没有这样的文件或目录 奇怪的是 该应用程序在我的笔记本电脑上运行得很好 下面是我正在使用
  • 基于时间窗口的不规则时间序列的优化滚动函数

    有没有办法使用 rollapply 来自zoo包或类似的东西 优化功能 rollmean rollmedian等 使用基于时间的窗口计算滚动函数 而不是基于大量观察的函数 我想要的很简单 对于不规则时间序列中的每个元素 我想计算一个具有 N
  • 相当于 min() 的 rowMeans()

    我在 R 邮件列表上多次看到这个问题 但仍然找不到满意的答案 假设我有一个矩阵m m lt matrix rnorm 10000000 ncol 10 我可以通过以下方式获得每行的平均值 system time rowMeans m use

随机推荐