R语言处理数据或分析时,很多时候要写连续输入输出代码,传统书写方式会引入一大堆中介变量,或者使用函数嵌套进行一次性输出。以上两种方法虽然从结果来看可以达到预期效果,但是无论是代码效率还是内存占用都存在巨大劣势
1.中介变量会使得内存开销成倍增长,特别是原始数据量非常大而内存有限,在处理过程中引入太多中介对象,不仅代码冗余内存也会迅速透支
2.函数嵌套则避免了内存占用问题,但是嵌套太多层函数,会造成代码难以理解,阅读困难,甚至给今后的项目复用造成很大的困扰
R引入管道操作符函数,进行连续传参,实现了内存节省、代码优化的需求。通常使用最多的管道函数来自于magrittr包,该包中管道操作函数%>%在R中使用非常频繁,很多比较成熟的项目扩展包都已经实现了管道操作函数的内置(比如dplyr、rvest、leaflet等都实现了默认调用)
library("rvest")
library("stringr")
url<-"http://www.zyzw.com/twzs010.html"
#读取url所在的目标网页
Name<-read_html(url,encoding="GBK") %>%
#选择b节点内容
html_nodes("b") %>%
#获取b节点内的文本(清除空格)
html_text(trim=FALSE) %>%
#替换掉文本内的所有制表符\标点符号等,使用gsub函数
gsub("(\\n\\t|,|\\d|、)","",.) %>%
#筛选出非空文本
grep("\\S",.,value=T) %>%
#清除掉文本两侧的空格
str_trim(side="both") %>%
#保留字符串向量的1:54个观测值
.[1:54]%>%
#剔除掉其中的第35、39个观测值
.[setdiff(1:54,c(35,39))]
#以上代码使用管道操作函数依次将左侧独享作为参数传入右侧函数内部,层层传递,不创建任何中间变量,因而这一段代码自url输入起始,到setdiff筛选完毕之后输出NAME终止,没有生成任何中间变量-意味着没有浪费任何多余内存.从代码的简介与优雅程度来看,它也完胜前两者,因为每一句功能都可以通过%>%看到明显的输入输出,当你回看或者修改时,仅需定位到对应代码块调试即可
关于参数传递的细节:
1.当函数仅需一个必要参数时,则此时函数写法容忍度非常高,相对自由:
sample(letters[1:5],size=20,replace=TRUE) %>% table()
sample(letters[1:5],size=20,replace=TRUE) %>% table
sample(letters[1:5],size=20,replace=TRUE) %>% table(.)
a b c d
5 7 1 7
以上三种写法都可以输出正确的结果,第一种写法保留了括号,第二种写法省略了括号,第三种同时保留了括号和占位符“.”
因为table只接受一个位置参数(也可以理解为必备参数,该参数是一个因子或者类别型变量)从左侧由管道操作符传入的参数就会被作为table的必备参数.前两种写法等价,第三种写法在括号内加入了占位符
2.当函数有一个以上的必备参数时,而且管道函数传入的参数位于第一个时,可以写成如下模式:
url %>% read_html(encoding="GBK")
url %>% read_html(.,encoding="GBK")
read_html函数中仅有一个位置参数x(必备参数),encoding是一个默认参数,options也是一个默认可选参数.因而x是必备参数,且无需声明参数名称.url被%>%传入read_html之后,默认就被作为x参数的对象.以上两种写法等价,第二种写法声明了x参数在read_html()函数内的位置(相当于x参数的占位符)但是在此种情况下并不必要(因为x作为第一个位置参数,可以被默认识别出来)
3.当函数有不止一个位置参数(必备参数)时,且左侧传入对象在右侧函数中不是位置排在第一个,那么此种情况下必须显式声明该参数在右侧函数中所处的位置,并且使用.作为占位符占位
read_html(url,encoding="GBK") %>% html_nodes("b") %>% html_text(trim = FALSE) %>% gsub("(\\n\\t|,|\\d|、)","",.)
#magrittr包为了保证管道函数传参过程更为高效,提供了很多类似%>%的辅助函数:
#以下函数中有经常用到的四则运算、逻辑判断与比较函数、包含关系函数等,也有一些使用频率不高的冷门函数
函数名称: 函数符号表达式:
extract "[" #用于索引数据框中的列
extract2 "[[" #索引列表中的顺序对象
inset "[<-"
inset2 "[[<-"
use_series "$"
add "+"
subtract "-"
multiply_by "*"
raise_to_power "^"
multiply_by_matrix "%*%"
divide_by "/"
divide_by_int "%/%"
mod "%%"
is_in "%in%"
and "&"
or "|"
equals "=="
is_greater_than ">"
is_weakly_greater_than ">="
is_less_than "<"
is_weakly_less_than "<="
not ("n'est pas") "!"
set_colnames "colnames<-"
set_rownames "rownames<-"
set_names "names<-"
例子:
#以下等价
iris %>% extract(,1:3) %>% head
iris %>%"["(1:3) %>% head
iris %>% .[,1:3] %>% head