|>(管道大于)在 R 中是什么意思?

What does |> (pipe greater than) mean in R?

提问人:Ian Campbell 提问时间:5/29/2021 最后编辑:Konrad RudolphIan Campbell 更新时间:8/3/2023 访问量:23597

问:

我最近在 R 中遇到了代码。它是一个垂直线字符(管道),后跟一个大于符号。|>

下面是一个示例:

mtcars |> head()

代码在做什么?|>

管道 操作员 R-FAQ

评论


答:

57赞 Ian Campbell 5/29/2021 #1

|>是基本的 R“管道”运算符。它在 4.1.0 版中是新的

简而言之,管道运算符将运算符的左侧 (LHS) 的结果作为右侧 (RHS) 的第一个参数。

请考虑以下几点:

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

在这里,数字 1 到 3 的向量作为函数的第一个参数提供。sum

左边的结果总是成为右边调用的第一个参数。考虑:

args(sum)
#function (..., na.rm = FALSE) 

c(1:3, NA_real_) |> sum(na.rm = TRUE)
#[1] 6

强调调用很重要,因为只要命名第一个参数,就可以将 LHS 重定向到其他参数。考虑:

args(rnorm)
#function (n, mean = 0, sd = 1) 
100 |> rnorm(n = 5)
#[1]  99.94718  99.93527  97.46838  97.38352 100.56502

args(sum)
#function (..., na.rm = FALSE) 
sum(na.rm = TRUE, ... = c(1:2,NA_real_))
#[1] 3
TRUE |> sum(... = c(1:2,NA_real_))
#[1] NA

使用运算符的一个好处是,与嵌套函数调用相比,它可以使代码在逻辑上更容易理解:|>

split(x = iris[-5], f = iris$Species) |>
  lapply(min) |>
  do.call(what = rbind) 
#           [,1]
#setosa      0.1
#versicolor  1.0
#virginica   1.4

#Compared to:
do.call(rbind,lapply(split(iris[-5],iris$Species),min))

此功能类似于 magrittr::%>% 运算符(也在 中实现)。dplyr

然而,与 不同的是,目前没有办法将 LHS 多次输送到右侧或任意位置。Magrittr 使用 LHS 的占位符并任意放置它。%>%.{}

library(magrittr)
iris[iris$Sepal.Length > 7,] %>% subset(.$Species=="virginica")

TRUE %>% {sum(c(1:2,NA_real_),na.rm = .)}
[1] 3

此外,与基础 R 不同,运算符可以通过管道进入函数调用,而无需:|>%>%()

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

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

评论

1赞 LMc 5/29/2021
还值得注意的是,这会抛出一个错误: 而这不会 .1:3 |> sum1:3 %>% sum
1赞 akrun 5/29/2021
您可以使用匿名函数TRUE |> {\(x) sum(c(1:2,NA_real_), na.rm = x)}()# [1] 3
0赞 Ian Campbell 5/29/2021
@akrun我实际上也想做一个问答,但也许你想这样做?\()
1赞 G. Grothendieck 5/29/2021
明显地。这就是我要说的。
2赞 moodymudskipper 5/30/2021
我认为值得一提的是,它被解析为 ,这与 {magrittr} 有很大的区别1:3 |> sum()sum(1:3)
12赞 jay.sf 3/29/2022 #2

要查看管道代码是如何解析的,我们可以使用 .quote()

例子:

quote(1:3 |> sum())
# sum(1:3)

quote(100 |> rnorm(n = 5))
# rnorm(100, n = 5)

quote(split(x = iris[-5], f = iris$Species) |>
        lapply(min) |>
        do.call(what = rbind))
# do.call(lapply(split(x = iris[-5], f = iris$Species), min), what = rbind)
8赞 Jakob 11/23/2022 #3

由于我最近在同行的代码中偶然发现了这个管道,我研究了这个主题,发现从 R 4.2 开始,您还可以在任意位置(但是,不是多次,只能一次)和不同的语法将 LHS 管道到右侧:

从 R 4.2 开始:可以与|>_

这意味着,基础 R 也可以执行 magittr 所做的一些工作:

# magittr
library(magrittr)
TRUE %>% sum(c(1:2, NA_real_), na.rm = .)

# R 4.2 onwards
TRUE |> sum(c(1:2, NA_real_), na.rm = _)

从 R 4.1 开始,可以与通过管道传递到的变量结合使用=>|> a => f(..., x = a, ...)

# R 4.1 onwards
# you have to set the '_R_USE_PIPEBIND_' envvar to a true value to enable =>
Sys.setenv("_R_USE_PIPEBIND_"=TRUE)
TRUE |> a => sum(c(1:2, NA_real_), na.rm = a)

评论

0赞 Dongdong Kong 6/27/2023
TRUE |> {sum(c(1:2,NA_real_),na.rm = _)}错误:管道的 RHS 调用不支持函数“{”
0赞 jay.sf 8/3/2023
@DongdongKong我关心它,但我认为卷曲的牙套是矫枉过正的。