magrittr | R语言的管道操作符

管道操作符(Pipe Operator)是一个特定的符号,它可以将前一行代码的输出传递给后一行代码作为输入,从而将原本相互独立的两行代码连接在一起。而通过不断地使用管道操作符,最终可以将多行代码写成“流”的形式。使用管道操作符既可以简化代码,又可以使代码间的逻辑关系更加清晰,还可以省去中间变量的输出。

R中的管道操作符包括%>%%T>%%<>%%$%,分别实现不同功能,这些管道操作符均来自magrittr工具包。其中%>%作为R代码的必备工具,同时也为tidyverse系列的dplyr工具包所继承,因此我们可以通过加载这三个工具包中的任何一个来调用它,而另外三种管道操作符只能通过加载magrittr来调用,不过它们本身的应用场景也不及%>%丰富,使用频率相对较低,而%>%则几乎成为R编程的必备工具。

1 %>%

如果一行代码需要输入的参数值刚好是它前一行的输出结果,可以使用%>%省略中间的输入过程。

比如我们要根据R自带的数据集mtcars,生成与它行数相同的一组随机数:

# 导入数据
data <- mtcars
# 计算行数
n <- dim(mtcars)[1]
# 生成随机数
rdn <- runif(n = n, min = 0, max = 100)

我们发现从第二行开始,它的输入参数就是它前一行的输出结果,因此可以使用%>%进行改写:

# load package
library(tidyverse) # 或者library(magrittr) 

mtcars %>%
  dim() %>%
  pluck(1) %>%
  runif(min = 0, max = 100) -> rdn

如果参数是位于第一的位置可以直接省略(大多数都是这种情况),其他位置的参数照常书写。比如上面dim()函数只需要第一个参数,且恰好是前一行的输出结果n,使用管道操作符后函数内就不需要在书写任何内容了;而runif()需要三个参数,其中第一个参数是前一行的输出结果,就只需要写其他两个参数。

另外这个过程不需要对中间变量进行命名,直到最后结果输出再进行命名。如果不使用管道操作符并且不对中间变量进行命名,也可以写出如下形式:

rdn <- runif(n = dim(mtcars)[1], min = 0, max = 100)

虽然以上代码也可以省去中间命名变量的麻烦,且看起来也很简洁,但是它的嵌套结构变得复杂了。实际使用时这种写法可以和%>%相结合,先把复杂的嵌套结构分解成若干较简单的嵌套结构再用%>%进行连接。

参数不是位于第一的位置,需要额外使用占位符

比如我们需要使用mtcars第一列变量的最小值控制生成随机变量的最小值:

# 导入数据
data <- mtcars[,1]
# 计算最小值
min <- min(data)
# 生成随机数
rdn <- runif(n = 20, min = min, max = 100)

# 使用管道操作符
mtcars %>%
  pluck(1) %>%
  min() %>%
  runif(n = 20, ., max = 100) -> rdn

由于minrunif()第二个参数需要的输入值,因此需要在这个位置放个占位符.。如果不想指定参数位置,也可以通过声明参数名称来实现,即min = .

当有多个参数的输入值依赖于前面代码的输出结果时,需要结合大括号{}进行使用

比如我们需要根据mtcars第一列变量的行数、最小值和最大值来控制随机数的生成:

# 不使用管道操作符
data <- mtcars[,1]
n <- length(data)
min <- min(data)
max <- max(data)
rdn <- runif(n = n, min = min, max = max)

# 使用管道操作符
mtcars %>%
  pluck(1) %>%
  {
    n = min(.)
    min = min(.)
    max = max(.)
    runif(n = n, min = min, max = max)
  } -> rdn

这种写法需要注意以下几点:

  • 在{}内仍然需要对中间变量进行命名,但不会作为结果输出出来;
  • {}内的占位符.始终指代{}开始前的输出内容,该内容在{}即使位于第一个参数位置也不能被省略;
  • {}结束后的输出结果是{}内的最后一个完整语句的输出结果,其他语句的结果不会被输出。

2 %T>%

%T>%会接受前一行的输出结果,但不会把自己的输出结果传入下一行,如果下一行继续使用%>%进行参数传递,那么传递进去的参数仍然是%T>%前一行的输出结果。

比如我们想先观察mtcars第一列变量的分布状态后再决定runif()的参数:

data <- mtcars[1]
boxplot(data)
n <- length(data)
runif(n = n, min = 10, max = 35)

在这里插入图片描述

我们是在使用boxplot()观察了data中数据的分布状态后再决定了限制生成随机数的最小值和最大值,而不是直接使用boxplot()的输出结果,也就是中间出现了“停顿”,这时就可以使用%T>%进行改写:

# 必须加载这个包
library(magrittr)

mtcars %>%
  pluck(1) %T>%
  boxplot() %>%
  length() %>%
  runif(min = 10, max = 35)

%T>%后的一个语句的结果不能以“文本”的形式输出出来,因此后面接的通常是绘图、导出数据等操作,并且这项操作并不会影响后面的语句继续继承%T>%前面语句的输出结果作为参数。

3 %<>%

%<>%相比%>%额外的功能是它会在整段代码运行完后将运行结果直接返回给%<>%前面的变量并保存下来,省去了再次命名的步骤,而它的位置也必须接在一个变量名后。

比如我们对data进行一系列操作后结果仍然命名为data:

library(magrittr)

# 使用%>%
data <- mtcars
data %>%
  mutate(rdn = runif(n = dim(.)[1], 10, 20)) -> data

在对data进行操作后我们使用向右赋值符号->将数据仍然命名为data,如果使用%<>%可以省去这一步:

data <- mtcars
data %<>%
  mutate(rdn = runif(n = dim(.)[1], 10, 20))

需要注意以下几点:

  • %<>%必须接在一个变量后面,而管道操作符中途没有新的命名变量,实际上这决定了%<>%的位置必须紧接在第一行代码后,且只能使用一次;
  • 处理前后的变量必须同名。

4 %$%

%$%传递的不是前一行的输出结果本身,而是输出数据框的列名,可以允许后一行代码直接根据列名调用相应的数据。

比如我们想根据mtcars中hp列的分布情况来控制生成随机数:

mtcars %$%
  runif(n = length(hp), min = min(hp), max = max(hp)) -> rdn

在这里插入图片描述

  • 14
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值