开拓R措施包之忍者篇
当前位置:以往代写 > 其他教程 >开拓R措施包之忍者篇
2019-06-14

开拓R措施包之忍者篇

开拓R措施包之忍者篇

作为一个伪措施员,我在做与代码有关的工作时,老是抱以一个动机,即“简化手工劳动到极致”。在这篇文章里,我先容一下今朝我认为最简化的开拓R包的流程。本站作者胡荣兴曾经在09年写过一篇开拓R包的文章“在Windows中建设R的包的步调”,个中小部门内容跟着R自己的更新已颠末期,该文面向Windows,并且先容的都是一些正统要领,这里我先容一条“忍者”之路,但愿对各人开拓R措施包有所辅佐。这篇文章原来是去年年底规划写的,时至今天第四届中国R语言集会会议正在人民大学轰霹雳隆召开,索性把它写完,算是一份不加入的陈诉吧。

在我看来,R的扩展性主要表此刻R包中,操作附加包的形式,我们可以把一些通例的、模式化的事情打包起来供日常利用,在R包中我们还可觉得函数编写文档和说明,这样可以制止未来健忘一个函数是做什么的以及怎么用的(健忘了就查辅佐,?function.name),文档是措施的重要构成部门,我小我私家经常认为写文档的难度不亚于写代码;另外,R包还浮现了R的另一点扩展性,即它能融合其它底层语言,典范的就是C语言、C++和Fortran,但一般用户大概用不到这些成果,下文仅扼要先容一下。

一、东西

对Linux和Mac用户来说,只要装好了R,开拓R包的东西就已经具备,可跳过本节。Windows用户除了安装R之外,还需要Rtools和一套LaTeX措施,典范的如MikTeX。安装Rtools的进程中有一步需要留意,就是修改情况变量PATH,这个选项是需要选上的。对付R自己,还需要把它的bin路径放到情况变量PATH中去。说了半天,什么是PATH?这是个让大白的人抓狂、不大白的人苍茫的问题,不外找它比找拉登大概照旧稍微容易一点:

“我的电脑”(右键)–>“属性”–>“高级”–>“情况变量”–>“系统变量”–>PATH

这里我们可以看到陆续串路径。为什么系统要有个PATH变量?原因就是为了可以或许离开措施的路径以呼吁行方法来运行措施,这样使得措施员不必担忧你的措施装在什么位置。当你在呼吁行窗口(*nix系统下叫终端,Terminal)中敲入一个呼吁时,系统就会从这一系列的PATH路径中去找你敲的这个措施是否存在,假如存在就运行它。“开始”–>“运行”(可能快捷键Win + R),输入cmd回车运行,就会打开一个呼吁行窗口。假如你从来没用过这玩意儿,那你必定是Windows深度中毒者,不妨先玩玩dircd ..等呼吁。

前面说要把R的bin路径插手PATH,这个路径在哪儿?假如你记不住本身的R装在哪儿,不要紧,打开R,输入R.home('bin')就知道了。凡是是雷同于C:\Program Files\R\R-2.xx.x\bin\这样一个路径。说到这里,我还得绕道再说一句:安装R的时候只管装在一个不带版本号的目次下,不然未来更新很贫苦,并且每次装新版本的R还得再修改PATH变量,因为bin路径变了。关于这一点,我只能说R core们都太严谨了,上次我在R-devel邮件列内外被一群人打了个屁滚尿流,他们死活都不能接管把R的安装路径改成默认不带版本号的。

配置好R的路径之后,为了测试各类配置是否齐备,可以打开呼吁行窗口,输入一些常用呼吁看看可否执行:

R --version
ls
gcc --version

假如这些都没问题,就可以进入下一节了。这里敲R对呼吁行来说,就是看看PATH中那些路径里有没有一个路径下包括R.exe可能R.bat之类的可执行文件,这就是所谓的“离开路径运行措施”。由于*nix系统的措施打点方法和Windows差异(可执行文件凡是统一放在/bin/可能/usr/bin/目次下),所以凡是没有这些疾苦。

二、R包布局

写R包较好的参考莫过于R自身的手册“Writing R Extensions”(下文简称R-exts)。在R中打开HTML辅佐(help.start()),就可以瞥见这本手册,内容很长,不外大部门都是普通用户不必体贴的。我的发起如下:对新手而言,必需要相识R包的布局,所以1.1.1节和1.1.3节必读,而整个第2节大概是未来需要重复参考的(除非你记性很好);已经上路的用户可以接着看一些高级话题,如定名空间(1.6节)和底层语言的利用(第5节)等。

一个最简朴的包布局如下(括号中为相应表明):

pkg (包的名字,请利用一个有意义的名字,不要照抄这里的pkg三个字母)
|
|--DESCRIPTION (描写文件,包罗包名、版本号、标题、描写、依赖干系等)
|--R (函数源文件)
   |--function1.R
   |--function2.R
   |--...
|--man (辅佐文档)
   |--function1.Rd
   |--function2.Rd
   |--...
|--...

#p#分页标题#e#

DESCRIPTION文件是一个纯文本文件(没有扩展名,Windows用户可以用记事本或其它文本编辑器打开),其内容参考R-exts就大白了,留意只有几个字段是必需的,其它都可选。假如你的包依赖于此外包中的函数,那么可以在Depends一行中写上那些包的名字(逗号脱离)。假如这个包只需要引入(Imports)此外包中的函数,那么就在Imports中写那些包的名字。Depends和Imports有细微不同:前者将导致加载你的包时,依赖包也被明晰加载进来,用户可以直接利用这些包中的函数;后者不会导致那些包被明晰加载,只有你的包在挪用那些函数,但那些函数对用户是不行见的(除非用户明晰加载之)。这里涉及到定名空间问题,后文详述。

除了R和man文件夹之外,尚有一些大概有用的文件夹,如demo下面可以放一些演示R代码,这样用户可以利用demo()函数挪用这些演示,凡是这是除了示例之外的较好的展示包成果的方法;data文件夹下可以放数据,这些数据凡是是通过save()函数生存成*.rda文件放到这里;src文件夹下可以放其它语言的源代码,编译安装的时候这些代码会被编译为动态链接库文件(pkg.dll或pkg.so);inst文件夹下的任何文件在安装包的时候都将被复制到包的根目次下,譬喻这里可以放NEWS文件(包更新的动静)或CHANGELOG文件,inst下凡是尚有一个重要的子文件夹就是doc,这里可以放一个Sweave文件(*.Rnw),编译安装包的时候这个文件会被Sweave编译生成LaTeX文件继而生成PDF文档,这也是关于一个包的很重要的先容文档,称为Vignette。

对付心急的看官,到这里可以先忽略所有先容,直接写一个DESCRIPTION文件外加一个R文件夹,底下放一个*.R剧本文件,内里包括一个函数,然后其实就可以安装利用了。但这种大致的步伐不是持久之计,如前面所说,文档很重要,提醒本身也利便他人。

三、安装R包

装包很简朴,一句R CMD INSTALL pkg就可以。譬喻你的包文件夹路径为/a/b/c/pkg/,那么先在呼吁行窗口中切换到这个pkg的上层目次下,然后用前面的呼吁安装:

cd /a/b/c/
R CMD INSTALL pkg

这样就装好了,在R中可以通过library(pkg)加载进来利用。

四、忍者神龟

至此,好像听起来很简朴:写两个函数,扔在R文件夹下,然后R CMD INSTALL一下,完事。不写文档、以为定名空间神马的最讨厌了的人此刻简直可以退场了,接下来我们深入一些话题。

4.1 R文档与roxygen2

R-exts手册第2.1节给了一个简朴的文档示例,我们可以看到R文档的语法和LaTeX很像,都是一些宏呼吁,如\title{我是标题}可能\description{我是描写}。虽然,这些玩意儿你都可以手写,假如要稍微偷懒一下,也可以用package.skeleton()可能prompt()等函数来帮助生成Rd文件,这些函数都可觉得你生成一些空模板,你本身往内里填充内容。若你的包只有一两个函数,倒也无妨,轻松写写完事,要是你想维护30个函数,那你就会以为这种做法完全是坑爹。坑爹之处不只在于你要么手敲这些呼吁要么绕道用函数生成文档模板本身填充,更在于你得在man文件夹下维护R文件夹下的函数的文档!你每次更新R函数,都得战战兢兢记着了:尚有man文件夹下的某个*.Rd文件也许需要更新。

这并不是什么新鲜问题,所有的措施开拓都面对这样的问题,于是有人发现了Doxygen,大意是把文档融入到源文件中,凡是采纳的方法就是把文档写成一种非凡的注释,这样不会影响源文件的执行(因为注释会被忽略),同时也可以从注释中动态抽取文本生成文档(如HTML或LaTeX/PDF等),这个主意相当妙。开拓措施的时候只需要在同一个文件内操纵即可:举头望文档,垂头思函数。

roxygen2是一个R包(它的前任是roxygen,但已经遏制更新了),它实现了把特定注释“翻译”为R文档的事情,譬喻:

##' @author Yihui Xie
##' @source \url{http://cos.name}

会被翻译为:

\author{Yihui Xie}
\source{\url{http://cos.name}}

你大概会说,嗨,介有嘛啊!!留意这些注释是直接写在函数界说上方的,虽然,这么说你照旧不信。所以下面必需先容另一门暗器,也就是传说中的编辑器Emacs。

4.2 roxygen与Emacs

假如你到手敲那些##' 注释,那我虽然不会写这篇文章。曾经有两个软件我以为我永远都学不会,一个是Emacs,另一个是Photoshop;如今只剩下一个(我也不规划学了)。Emacs是我装了卸、卸了装高出10次的软件,终于在第11次搞大白了六指琴魔是怎么个练法。假如你也是新手,那么发起安装Vincent Goulet维护的修悔改的Emacs。修改之一就在于直接插手了ESS(Emacs Speaks Statistics),ESS是Emacs的一个插件,它提供了编辑器与其它统计软件(如SAS、S-Plus、R)的交互,譬喻可以通过快捷键把R代码发送到R里执行。

#p#分页标题#e#

ESS自己我以为也没啥,但ESS加上了roxygen的支持之后我就以为这是个忍者东西了。在Emacs中,光标放在R函数上,快捷键C-c C-o一按,就如同发出一把暗器,一个roxygen注释模板立即生成了。这一点让开拓R包不知道快了几多倍。也许有读者知道我在维护一个叫animation的R包,说实话,曾经有一段时间我实在不想维护了,因为写函数写文档太贫苦,直到买通了Emacs和roxygen关。

好嘛!听起来仿佛不错,咋用?装好Emacs之后,先去找个参考卡片,操练两天一些根基操纵(打开文件、生存文件之类的),熟悉一些根基观念(有些相当坑爹,譬喻剪切不叫剪切,叫杀,粘贴不叫粘贴,叫拉),虽然首先得知道C代表Ctrl键、M代表Alt键。再找个ESS参考卡片,看看根基的代码发送操纵。总而言之,常用的快捷键不多,不需要真的酿成六指琴魔。要是陷入了快捷键连锁陷阱(本身不知道按到那边去了),就以万能的C-g退出再来。

假设你已经装好了Emacs,此刻可以任意打开一个R文件:C-x C-f,输入文件名,回车,假如存在则会打开它,假如不存在,则会新建一个文件,留意作为一个(伪)措施员,你必需永远紧记:不要老诚恳实打字!能用Tab键的时候只管用,它在许多环境下都能自动补全(如路径、工具名称等)。这里的文件名应该以.R或.r为后缀,这样Emacs才知道应该用ESS来处理惩罚它,譬喻abc.R。此刻在编辑器界面内输入一个任意函数,如

stupid_f = function(a, b){
    a + b
}

然后把光标放在stupid_f这一行上,按C-c C-o,你就会发明你的文件酿成了雷同这样一个对象(按照ESS差异的设置,以下功效也许不完全沟通):

##' title...
##'
##' description...
##'
##' details here
##' @param a
##' @param b
##' @return
##' @author Yihui Xie <\url{http://yihui.name}>
##' @examples
stupid_f = function(a, b){
    a + b
}

接下来你的任务就是把该填的文档填上。roxygen2的通例是,第一段是标题(未来翻译为\title{}),段落之间以空行分隔,第二段是描写(\description{}),然后接着是这个函数的具体描写(\details{}),它可以是若干段落,你愿意写多长就写多长。剩下的@字段就不必多表明白,参数、返回值、作者、示例等,我们可以通过M-x customize-group,回车,ess,回车,来设置ESS中这些roxygen的默认字段。一个自然而然的问题就是,哪些字段是可用的?拜见roxygen2包的辅佐?rd_roclet。为了完全领略Rd文档和roxygen2字段的对应干系,你较好照旧读一下手册R-exts和这两个辅佐页面。留意ESS有许多利便的成果,好比你在roxygen注释之后回车,下一行会自动以##' 开头;在任意一个@标签后按M-q则可以把该段落自动折叠为短行,使得文本更整齐(这是我常常用的一个成果);假如函数中有新增加可能淘汰参数,那么只需要再次C-c C-o就可以自动更新上面的注释了,新增加的参数会自动加上新的@param,淘汰的参数会被自动删掉注释。

roxygen2还实现了一些自动成果,较量重要的就是对定名空间文件NAMESPACE和描写文件DESCRIPTION的自动更新,这些我们第五节再说。先说如何从roxygen注释翻译到Rd文档,很简朴:假如一个包已经按第二节的布局写好(不需要有man文件夹),函数和相应的roxygen注释都已经存在,那么用函数roxygenize()就可以把这样一个低级包翻译为一个完整R包了:

setwd('/a/b/c/')  # 先把事情目次切换到pkg之上
library(roxygen2)
roxygenize('pkg')

默认环境下新生成的R文档以及更新的NAMESPACE和DESCRIPTION都生成在包的目次下,此刻pkg就是一个完整的R包,包括自动生成的man文件夹,可以直接用R CMD INSTALL pkg安装。

天有不测风云,工作到这里还没完全竣事,roxygen包也有些坑爹的处所,它原来是2008年Google编程夏令营的产品,但作者自夏令营竣事之后投入维护的精神好像就越来越少,导致许多问题都一直没有批改。我在利用进程中实在忍不了,于是动手写了个基于roxygen之上的包Rd2roxygen(更新:roxygen包此刻已经被roxygen2代替了,后者在更新维护中)

4.3 反悔药包Rd2roxygen

#p#分页标题#e#

反悔药的意思是,有人瞥见roxygen是如此的利便,大为反悔,因为维护原始R包太费精神了,但是爹已经被坑了,已经凭据R-exts的要求老诚恳实写了那一大把*.Rd文件,肿么办?Rd2roxygen包降生的目标就是为了办理这个问题:roxygen是把注释翻译为Rd,而这个包倒过来,把Rd从头翻译回注释!给你反悔药吃。假如你是反悔的人中的一员,不妨参考这个包中的Rd2roxygen()函数;假如是新手,那么这个包的rab()函数大概是roxygen中的roxygenize()函数的一个很好的替代,个中我较量孤高的一个成果是它能自动整理示例代码,许多R包的示例代码都不足整齐(无空格无缩进等)。详情拜见辅佐文件及其先容文档(Vignette)。简言之,此刻我们利用:

library(Rd2roxygen)
rab('pkg')
## 假如要直接安装,那么rab('pkg', install=TRUE)

所有东西至此或许先容完毕。假如你还没昏死已往,请接着读第五节。

五、九霄云外

上面的对象刚上手时大概是有点晕,熟悉之后写包就立即追风逐电了。下面我们再先容几个略微高级的观念。

5.1 定名空间

定名空间(NAMESPACE)是R包揽理包内工具的一个途径,它可以节制哪些R工具是对用户可见的,哪些工具是以后外包导入(import),哪些工具从本包导出(export)。为什么要有这么个玩意儿存在?主要是为了更好打点你的一堆工具。写R包时,有时候大概会碰着某些函数只是为了别的的函数的代码更短而从中抽象、独立出来的,这些小函数仅仅供你本身利用,对用户没什么辅佐,他们不需要瞥见这些函数,这样你就可以在包的根目次下建设一个NAMESPACE文件,内里写上export(函数名)来导出那些需要对用户可见的函数。自R 2.14.0开始,定名空间是R包的强制构成部门,所有的包必需有定名空间,假如没有的话,R会自动建设。

前面我们也提到DESCRIPTION文件中有Imports一栏,这里配置的包凡是是你只需要其部门成果的包,譬喻我只想在我的包中利用foo包中的bar()函数,那么Imports中就需要填foo,而NAMESPACE中则需要写importFrom(foo, bar),在本身的包的源代码中则可以直接挪用bar()函数,R会从NAMESPACE看出这个bar()工具是从那边来的。

roxygen注释对这一类定名空间有一系列标签,如一个函数的文档中若标志了##' @export,那么这个函数未来就会呈此刻定名空间文件中(被导出),若写了##' @importFrom foo bar,那么foo包的bar工具也会被写在定名空间中。这些内容拜见R-exts的1.6节和roxygen2的?export辅佐。

5.2 先容文档(Vignette)

前面我们提到了inst/doc/目次,下面可以放一个Sweave文件,在R CMD INSTALL进程中这个Sweave文件会被执行并生成PDF文档,若Sweave文件中有一句注释:

%\VignetteIndexEntry{An Introduction to XXX}

那么这句话未来会呈此刻HTML辅佐页面中(点开链接“Overview of user guides and package vignettes”),譬喻Rd2roxygen包可能formatR包的辅佐页面中就有先容文档的链接。

5.3 其它语言

在src目次下我们可以安排一些其它语言的源代码,内里大概包括一些函数,这些函数在被编译之后,(以C语言为例)可以在R代码中以.C('routine_name', ..., package = 'pkg')的形式挪用,但要留意,假如需要用这个成果,在R目次下需要有一个zzz.R文件(这个非凡文件是用来在加载包之前加载运行的代码),内里写上:

.onLoad <- function(lib, pkg) {
    library.dynam("pkg_name", pkg, lib)  # pkg_name是你的包的名字
}

这些对象我并不在行,只先容到这里,具体内容还请深挖R-exts。另留意楼下Rtist的评论。

六、宣布

等你的包写好之后,还不能立即宣布,因为尚有很重要的一步要做,就是看它是否能通过R CMD check的查抄,这是你的包能宣布到CRAN上的前提。在呼吁行界面中输入(请确保pkg文件夹是一个完整的R包,即:假如你用roxygen2,那么这里要查抄的是运行过roxygen2之后的产品):

R CMD check pkg

R就会开始查抄这个包是否有语法错误以及是否切合类型。可能假如你用Rd2roxygen包的话,也可以在R内里挪用:

library(Rd2roxgyen)
rab('pkg', check = TRUE)  # 确保pkg文件夹在当前事情目次下:getwd()

#p#分页标题#e#

查抄进程会汇报你具体的日志信息,假如有错,你立即就能知道。这里每个函数的例子(假如有的话)城市被运行,假如例子代码有错,这里也会报错,所以这个进程也是一个很好的查抄本身的示例代码可否正确运行的测试。假如没有任何错误,那么就可以向CRAN提交了。提交的内容是一个压缩包,名为pkg_x.x-x.tar.gz,它是通过R CMD build pkg生成的。提交方法是通过FTP,拜见CRAN首页说明。留意上传完之后需要向CRAN打点员发一封邮件,通知他们你提交了一个包,今后每次更新时的流程也一样:FTP上传+邮件通知。今朝Kurt Hornik打点Linux包的编译,Uwe Ligges认真Windows包的编译,都是人工打点,要是碰上Kurt度假去了,你就得等着了(概率很小,不外我遇到过)。

七、后话

此刻CRAN上的附加包数目已经高出三千,充实浮现出R的精采扩展性和社区相助,要否则不会有这么多人去写R包(尽量这三千号包必定是良莠不齐)。我小我私家是07年底从动画包animation开始写起的(想当年,R包内里尚有微软的CHM辅佐)……过了几年又连续写了自动整理R代码的formatR包、把Rd转化为roxygen注释的Rd2roxygen包、把R图形转化为Flash动画的R2SWF包(与邱怡轩相助)、纯粹为了搞笑好玩的fun包(未宣布)、为我的《现代统计图形》书稿配备的MSG包、用图形界面挪用WinBUGS可能OpenBUGS的iBUGS包等。用麦兜的赞美就是:

大包再来两笼
大包再来两笼
大包再来两笼不怕撑
……

扯远了。

写了这么些包,有些感觉。首先,写代码有两样一般人不能领略的坚苦,一样前面已说,就是写文档,你得表明清楚参数的寄义、得给出有用的示例代码、写演示写先容文档等等,事情量其实很大;别的一样就是工具定名,我认为从工具的定名可以看出一个措施员的成熟水平,好的措施员,给的函数名既精辟又直观,这一点上必需服气R core团队,要是我写几千个函数,光是想名字都能把脑壳想爆了,这里顺便提一下我推荐的定名方法,要么用驼峰(someFunction),要么用下划线(some_function),只管不要用点(some.function),因为点在R语言中有一层非凡寄义(S3要领的类匹配),这也是我对animation包较量反悔的一点。其次,你较勤学会一样版本节制东西,如SVN可能GIT,不只是打点包,它在打点任何文本文件时都很是有用,也利于多人相助,我此刻倾向于GIT,主要是因为一个好网站的存在(GitHub),我的所有R包都已经从本来以SVN为基本的R-Forge上搬迁到了GitHub,可以在哪里参考我的包是怎么写的;不会版本节制东西的人的一个典范特征就是,电脑里存在一系列这样的文件:率领讲述20100101.doc、率领讲述20100102.doc……,版本节制东西可以让你很利便回到文件的汗青状态,也利便多人相助(譬喻将A的更新和B的更新自动归并)。最后,写包不只是对本身事情的一个不绝总结,不至于做完一件事就永远尘封之,并且也是很好的自我宣传途径,你在简历上写得口不择言,大概不如以一件作品更能深入人心。

    关键字:

在线提交作业