在R语言的数据处理中,一般来说,为了完成某项操作通常需要使用不止一个函数。往往需要把上一个函数的结果作为下一个函数的输入值,嵌套多次之后才得到最终的结果。在这种情况下,无论是使用一连串括号把函数嵌套起来,还是定义一系列中间变量一步一步做下去,都会显得繁琐而逻辑不清。举个例子,假如我们想计算出http://blog.csdn.net/weixin_40628687页面中所有博文的点击量最大是多少,大概需要下面5个步骤:
library(rvest)
# 下载网页页面
url <-'http://blog.csdn.net/weixin_40628687'
webpage <-read_html(url)
# 定位链接位置
xpath <-'//*[@id="main"]/div/ul[2]/li[2]/ul[2]/li/a/div/div/div[3]/span'
content <-html_nodes(webpage, xpath = xpath)
# 提取数字
number <-html_text(content, trim = T)
# 转化为numeric格式
number <-as.numeric(number)
# 最大值
max(number)
如果使用嵌套的话,逻辑更加混乱:
url <-'http://blog.csdn.net/weixin_40628687'
xpath <-'//*[@id="main"]/div/ul[2]/li[2]/ul[2]/li/a/div/div/div[3]/span'
max(as.numeric(html_text(html_nodes(read_html(url),xpath = xpath), trim = T)))
其实处理这种情况,R语言中有一些小技巧:
1、管道操作符
一些R语言包(如pipeR、rvest、magrittr等)定义了管道操作符(%>%),其思想是“%>%”表示将符号左边的值输出为右边调用的函数的第一个参数。上面的例子可以写成:
url %>%
read_html %>% # 读取网页
html_nodes(xpath =xpath) %>% # 寻找节点
html_text(trim = T)%>% # 提取数字
as.numeric %>% # 转化格式
max # 求取最大值
层次和逻辑就清晰了很多。
2、Reduce系列函数
某些函数,例如集合运算(交、并、差),只能在两个对象间进行,然而实际使用时,我们要处理的对象常常要多于两个,如果使用嵌套的方法处理,既繁琐又容易少写括号,此时我们可以使用Reduce函数。
Reduce(f, x, init, right = FALSE, accumulate = FALSE)
其中,参数x是要处理的向量(可以是list),参数f是处理x所使用的的函数,Reduce函数的目的就是使用f函数对x数据从左到右依次迭代计算,当参数right为TRUE时迭代顺序为从右往左,参数accumulate为TRUE时每一步迭代的结果都会输出。
例如,我们要计算多个集合的交集:
a <- c(1, 3, 5, 7, 9)
b <- c(1, 2, 3, 4, 5)
c <- c(1, 2, 3, 5, 7)
d <- c(1, 2, 3, 5, 8)
# 嵌套(形式繁琐)
intersect(a, intersect(b, intersect(c, d)))
# Reduce迭代
Reduce(intersect, list(a, b, c, d))