如何在base R('base pipe')中进行管道传输?

toe95027  于 2023-04-18  发布在  其他
关注(0)|答案(3)|浏览(151)

有没有一种方法可以在base R中使用管道,而不必定义自己的函数(即“开箱即用”的东西),也不必加载任何外部包?
也就是说,一些(基R)替代magrittr管道%>%
这个功能在R 4.0.3中可用吗?如果没有,在哪个R版本中可以找到,如果有,是如何实现的?

lztngnrs

lztngnrs1#

在R中,|>用作管道操作符。(从4.1.0开始)
左侧表达式 lhs 作为第一个自由参数插入到右侧表达式 rhs 的调用中。

mtcars |> head()                      # same as head(mtcars)
#                   mpg cyl disp  hp drat    wt  qsec vs am gear carb
#Mazda RX4         21.0   6  160 110 3.90 2.620 16.46  0  1    4    4
#Mazda RX4 Wag     21.0   6  160 110 3.90 2.875 17.02  0  1    4    4
#Datsun 710        22.8   4  108  93 3.85 2.320 18.61  1  1    4    1
#Hornet 4 Drive    21.4   6  258 110 3.08 3.215 19.44  1  0    3    1
#Hornet Sportabout 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2
#Valiant           18.1   6  225 105 2.76 3.460 20.22  1  0    3    1

mtcars |> head(2)                     # same as head(mtcars, 2)
#              mpg cyl disp  hp drat    wt  qsec vs am gear carb
#Mazda RX4      21   6  160 110  3.9 2.620 16.46  0  1    4    4
#Mazda RX4 Wag  21   6  160 110  3.9 2.875 17.02  0  1    4    4

也可以在 rhs 调用中使用命名参数和占位符_来指定 lhs 的插入位置。占位符只能在 rhs 上出现一次。(自4.2.0起)

mtcars |> lm(mpg ~ disp, data = _)
#mtcars |> lm(mpg ~ disp, _)  #Error: pipe placeholder can only be used as a named argument
#Call:
#lm(formula = mpg ~ disp, data = mtcars)
#
#Coefficients:
#(Intercept)         disp  
#   29.59985     -0.04122

或者在“one”之前显式地命名参数:

mtcars |> lm(formula = mpg ~ disp)

如果占位符被多次使用,或者在任何位置上用作命名或未命名的参数,或者用于禁用的函数:使用(匿名)函数

mtcars |> (\(.) .[.$cyl == 6,])()
#mtcars ->.; .[.$cyl == 6,]           # Alternative using bizarro pipe
#local(mtcars ->.; .[.$cyl == 6,])    # Without overwriting and keeping .
#                mpg cyl  disp  hp drat    wt  qsec vs am gear carb
#Mazda RX4      21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4
#Mazda RX4 Wag  21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4
#Hornet 4 Drive 21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1
#Valiant        18.1   6 225.0 105 2.76 3.460 20.22  1  0    3    1
#Merc 280       19.2   6 167.6 123 3.92 3.440 18.30  1  0    4    4
#Merc 280C      17.8   6 167.6 123 3.92 3.440 18.90  1  0    4    4
#Ferrari Dino   19.7   6 145.0 175 3.62 2.770 15.50  0  1    5    6

mtcars |> (\(.) lm(mpg ~ disp, .))()
#Call:
#lm(formula = mpg ~ disp, data = .)
#
#Coefficients:
#(Intercept)         disp  
#   29.59985     -0.04122

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 

#The same but over a function
._ <- \(data, expr, ...) {
  eval(substitute(expr), list(. = data), enclos = parent.frame())
}
1:3 |> ._(setNames(., .))
#1 2 3 
#1 2 3

某些功能已禁用。

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

但是有些仍然可以通过将它们放置在brake中来调用,通过函数::调用它们,在函数中调用它或定义函数的链接。

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

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

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

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

一个写为x |> f(y)的表达式被解析为f(x, y)。当管道中的代码被顺序写入时,用于求值的常规R语义适用。因此管道表达式仅在 rhs 表达式中首次使用时才会被求值。

-1 |> sqrt() |> (\(x) 0)()
#[1] 0

. <- -1
. <- sqrt(.)
#Warning message:
#In sqrt(.) : NaNs produced
(\(x) 0)(.)
#[1] 0

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 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

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

dced5bon2#

你可以使用bizarro pipe(也叫this),它巧妙地使用了现有的语法,不需要函数或包。

mtcars ->.;
  transform(., mpg = 2 * mpg) ->.;   # change units
  lm(mpg ~., .) ->.;
  coef(.)

其中->.;看起来像一个管道。

b4qexyjb

b4qexyjb3#

在撰写本文时,R的发布版本(4.0.3)不包含管道操作符。
但是,正如在useR! 2020 keynote中所指出的,基础|>运算符正在开发中。
来自2020-12-15 R-devel daily sourcepipeOp手册页:
管道表达式将lhs表达式的结果通过管道传递到rhs表达式。
如果rhs表达式是一个调用,那么lhs将作为调用中的第一个参数插入。因此x |> f(y)将被解释为f(x, y)。为了避免歧义,rhs调用中的函数在语法上可能不是特殊的,例如+if
如果rhs表达式是一个function表达式,则调用函数时将lhs值作为其参数。当lhs需要作为rhs调用中的第一个参数以外的参数传递时,这很有用。
该操作符何时会进入发布版本,或者在发布之前是否会更改,目前尚不清楚。

相关问题