F#语言中的|>符号实现了|>
x f = f x 这样的计算,即符号右边给定一个函数,用左边的结果作为参数传递给这个函数,进行计算。例如:
<br />
let data =<br />
[|1..100|]<br />
|> Array.filter (fun i -> i*i <= 50)<br />
|> Array.map (fun i -> i+i*i)<br />
|> Array.sum<br />
</p>
即使不懂F#语言,基本也能猜出上面的代码做了什么。|>符号称为pipeline operator。在R语言中,也可以实现这种类型的符号,可以大大简化流程式的数据变换和操作。Hadley的dplyr扩展包(https://github.com/hadley/dplyr)中实现的%.%就实现了把前面计算的结果Pipe到后面函数作为第一个参数,而magrittr扩展包(https://github.com/smbache/magrittr)中实现的%>%则可以把前面的计算结果pipe到后面函数的第一个参数或者pipe给.符号由后面一个函数使用。但是,dplyr中的%.%功能单一,而magrittr中定义的%>%虽然特性更多但是只能在一层参数上提供.符号的pipe(为了避免许多bug和冲突),因此我最近写了一个pipeR包(https://github.com/renkun-ken/pipeR)实现两种pipeline operator:%>%为first-argument piping,%>>%为free piping.
小例子:
pipeR可以允许嵌套很多的表达式
<br />
plot(diff(log(sample(rnorm(10000,mean=10,sd=1),size=100,replace=FALSE))),col="red",type="l")<br />
</p>
重新表述为符合操作顺序的
<br />
rnorm(10000,mean=10,sd=1) %>%<br />
sample(size=100,replace=FALSE) %>%<br />
log %>%<br />
diff %>%<br />
plot(col="red",type="l")<br />
</p>
甚至功能更丰富的
<br />
rnorm(10000,mean=10,sd=1) %>>%<br />
sample(.,size=length(.)*0.2,replace=FALSE) %>>%<br />
log %>>%<br />
diff %>>%<br />
plot(.,col="red",type="l",main=sprintf("length: %d",length(.)))<br />
</p>
还有一个更复杂一点的例子:
<br />
library(dplyr)<br />
library(hflights)<br />
data(hflights)</p>
<p>hflights %>%<br />
mutate(Speed=Distance/ActualElapsedTime) %>%<br />
group_by(UniqueCarrier) %>%<br />
summarize(n=length(Speed),speed.mean=mean(Speed,na.rm = T),<br />
speed.median=median(Speed,na.rm=T),<br />
speed.sd=sd(Speed,na.rm=T)) %>%<br />
mutate(speed.ssd=speed.mean/speed.sd) %>%<br />
arrange(desc(speed.ssd)) %>>%<br />
assign("hflights.speed",.,.GlobalEnv) %>>%<br />
barplot(.$speed.ssd, names.arg = .$UniqueCarrier,<br />
main=sprintf("Standardized mean of %d carriers", nrow(.)))<br />
</p>
GitHub repo中具体介绍了例子,我的一篇小文(http://renkun.me/blog/r/2014/04/08/use-pipeline-operators-in-r.html)也有更多介绍。欢迎大家使用pipeR,或者参与到开发中!如果发现有问题的地方,或者需要改进的地方,欢迎到github提出issue!
目前该扩展包没有提交到CRAN,因此安装需要devtools扩展包。下面是安装pipeR的R代码:
<br />
if(!require(devtools)) install.package(devtools)<br />
require(devtools)<br />
install_github("renkun-ken/pipeR")<br />
</p>