最近学习到Linux的管道符
|
可以将左侧的输入传递给右侧的函数处理,这种从左到右的函数处理方式看着就让人很舒服,想起R中其实也有这种类似的管道符 –%>%
。因此,就在这篇文章谈谈%>%
的基本特点和包含它的包magrittr
magrittr - Ceci n’est pas un pipe.
Ceci n’est pas un pipe 是一句法语,翻译过来的意思是 “这不是管道符”。
记得第一次看到这样的代码的时候就忍不住头大,这个%>%
到底是个啥?
1 | rnorm(10) %>% as.character %>% sort %>% unique |
在翻阅了多个网站的资料后,才知道%>%
的功能就是把左侧的变量传递给右边。而上面的函数也就是相当于把嵌套的函数unique(sort(as.character(rnorm(10))))
用%>%
写出来。
当时对%>%
的第一感受就是可以简化函数嵌套的表达模式,用一种更简洁且优美的方式敲代码。但%>%
就止步于此了吗?
在了解%>%
之前,我们要先弄明白 Stefan Milton Bache写这个包想要解决的问题是什么?
从magrittr
的R Documents上了解到,其提供了一系列操作符,可以解决以下问题
- 以一种从左到右的方式构建数据操作的顺序
- 避免函数嵌套式调用
- 减少局部变量的创建和部分函数的定义
- 简单地在代码序列中添加步骤
一句话总结magrittr
管道符的优点就是大大地提高了代码的可读性(readable),减少到几乎不需要局部变量的创建,并降低程序对内存的占用。
Installation
1 | install.packages("magrittr") |
Usage
%>%
: 管道操作符,将左侧变量传递到右侧并作为输入变量.
%>%
的基本用法
先从最基本的%>%
开始,其用法也十分简单,基础的用法就是 x %>% f
== f(x)
x %>% f
默认将x
传递到函数的第一个参数位,无论后面有无参数,即 x %>% f(y)
== f(x,y)
像一开始的例子一样,多级函数传递也是可以的,x %>% f %>% g %>% h
== h(g(f(x)))
拿iris
数据做个例子
1 | # 第一种用法 |
Placeholder | 占位符.
x %>% f(y, .)
== f(y, x)
用.
可作为placeholder,指明左侧输入传递到的位置。如果没有的话,默认左侧输入传递到右侧函数的第一个参数。
1 | > "Ceci n'est pas une pipe" %>% gsub("une", "un", .) |
传递给多个参数 | {}
在嵌套函数中使用.
方法时需要格外注意以下情况的发生:
x %>% f(y=nrow(.), z=ncol(.))
== f(x, y=nrow(x), z=ncol(x))
虽然使用.
后,变量x
会传递到.
处,但是x
也传递到函数f
的第一个参数位。
想要避免这种情况的发生可以使用{}
将函数包起来,即x %>% {f(y=nrow(.), z=ncol(.))}
== f(y=nrow(x), z=ncol(x))
1 | > set.seed(501) |
在创建函数中使用管道符
利用管道符构建函数也是十分简单的,我们可以使用.
作为管道传递的起始,它将会返回一个函数,例如:f <- . %>% cos %>% sin
== f <- function(.) sin(cos(.))
其他管道符
magrittr
包还提高了其他几种管道符,以在特殊的情景进行利用,下面会简单介绍这几种符号。
%<>%
赋值代码流的结果给一个变量
%<>%
:相当于<- %>%
的组合, 同样是将左侧变量传递到右侧并作为输入变量,但会将最后的结果赋值到最左侧的变量。1
2
3
4a <- rep(c(2,3), each =10)
a %<>% as.character %>% unique
a
## [1] "2" "3"
%T>%
分支管道符
%T>%
: 将左侧传递到右侧,右侧执行后返回左边的原始输入,而非执行后结果。
以下的代码从标准正态分布中随机取样200个数,并构建出100 x 2
的矩阵,最后对列求和。唯一不同在于第二条代码使用 %T>% plot
对矩阵画了个散点图,再将矩阵传递给colSums
。
1 | > rnorm(200) %>% matrix(ncol = 2) %>% colSums |
所以%T>%
的一种应用环境就是当操作序列中间有像plot
这种不返回结果的函数时,既将左侧变量传递给这种函数,又不会影响后边函数的处理。
%$%
创建变量局部环境
%$%
: 可以将左侧变量中的变量名传递到右侧应用。有些函数,如ggplot
,在输入数据后可以用数据框中的变量名来调用数据框内的变量(例如:ggplot(data,aes(x=x1,y=x2))
)。%$%
就是发挥这样的功能,我们可以用下面这个例子来理解
1 | iris %>% |
上面的代码就是先截取iris
数据中Sepal.Length
列大于平均值的部分,再在截取后的iris
数据中使用cor
计算Sepal.Length
和Sepal.Width
的相关性。与下面的代码是等价的
1 | a <- iris %>% subset(Sepal.Length > mean(Sepal.Length)) |
通过这个例子,我们可以看到使用%$%
这一管道符,其实相当于在符号的右侧创建了一个局部环境,在该环境中可以直接以名字的方式调用左侧传递过来的变量,而省略$
。
以上的这些管道操作符在magrittr
, dplyr
, tidyverse
包都能找到,加载其中一者即可使用。
完。
参考资料:
https://www.rdocumentation.org/packages/magrittr/versions/1.5