在巨人的肩膀前行 催化R包开发

R的极客理想系列文章,涵盖了R的思想,使用,工具,创新等的一系列要点,以我个人的学习和体验去诠释R的强大。

R语言作为统计学一门语言,一直在小众领域闪耀着光芒。直到大数据的爆发,R语言变成了一门炙手可热的数据分析的利器。随着越来越多的工程背景的人的加入,R语言的社区在迅速扩大成长。现在已不仅仅是统计领域,教育,银行,电商,互联网….都在使用R语言。

要成为有理想的极客,我们不能停留在语法上,要掌握牢固的数学,概率,统计知识,同时还要有创新精神,把R语言发挥到各个领域。让我们一起动起来吧,开始R的极客理想。

关于作者:

  • 张丹(Conan), 程序员Java,R,PHP,Javascript
  • weibo:@Conan_Z
  • blog: http://blog.fens.me
  • email: bsspirit@gmail.com

转载请注明出处:
http://blog.fens.me/r-package-faster/

r-devtools

前言

开发自己的R包sayHello 一文中,我们看到了如何从底层,按照R语言的标准构建一个R语言的扩展包。但实施过程确实复杂,会让很多的统计学工作者望而却步。如果能有一种比较简单方式,简化开发过程,那该多好啊!

我们是幸运的,Hadley Wickham(ggplot2,plyr的作者)已经帮我们梳理出了一套开发流程。站在巨人的肩膀上,看得更高,走得更远。

目录

  1. 开发流程介绍
  2. 编写功能代码
  3. 调试程序
  4. 单元测试
  5. 撰写文档
  6. 程序打包
  7. 程序发布

1. 开发流程介绍

站在巨人的肩膀,开发R包我们有3个武器:devtools, roxygen2, testthat

  • devtools:让开发变得简单,各种开发小工具的合集,非常实用。
  • roxygen2:通过注释的方式,生成文档,远离Latex的烦恼。
  • testthat:单元测试,让R包稳定、健壮,减少升级的痛苦。

标准化的开发流程:

  1. 编写功能代码
  2. 调试程序
  3. 单元测试
  4. 撰写文档
  5. 程序打包

2. 编写功能代码

1). 安装程序包:devtools, roxygen2, testthat


#依赖库
~ sudo apt-get install libcurl4-openssl-dev
~ sudo apt-get install libxml2-dev

#请使用root权限启动R
~ sudo R

> install.packages("devtools")
> install.packages("roxygen2")
> install.packages("testthat")

> library(devtools)
> library(roxygen2)
> library(testthat)

#查看
> search()
 [1] ".GlobalEnv"        "package:testthat"  "package:roxygen2"
 [4] "package:digest"    "package:stats"     "package:graphics"
 [7] "package:grDevices" "package:utils"     "package:datasets"
[10] "package:methods"   "Autoloads"         "package:base"

构建工程chinaWeather
创建骨架,代替package.skeleton()


> setwd("/home/conan/R")

> create("/home/conan/R/chinaWeather")
Creating package chinaWeather in /home/conan/R
No DESCRIPTION found. Creating default:

Package: chinaWeather
Title:
Description:
Version: 0.1
Authors@R: # getOptions('devtools.desc.author')
Depends: R (>= 3.0.1)
License: # getOptions('devtools.desc.license')
LazyData: true

> setwd("/home/conan/R/chinaWeather")
> dir()
[1] "DESCRIPTION" "man"         "R"

编辑DESCRIPTION文件

~ vi /home/conan/R/chinaWeather/DESCRIPTION
Package: chinaWeather
Type: Package
Title: a visualized package for china Weather
Description: a visualized package for china Weather
Author: Dan Zhang
Maintainer: Dan Zhang
Version: 0.1
Depends: R (>= 3.0.1)
License: GPL-2
LazyData: true
Date: 2013-08-05

增加函数文件chinaWeather.R


~ vi /home/conan/R/chinaWeather/R/chinaWeather.R

#define a filename from current date
filename<-function(date=Sys.time()){
  paste(format(date, "%Y%m%d"),".csv",sep="")
}

3. 调试程序

加载程序包到R中


> load_all("/home/conan/R/chinaWeather")
Loading chinaWeather

> filename
function(date=Sys.time()){
  paste(format(date, "%Y%m%d"),".csv",sep="")
}


> filename()
[1] "20130805.csv"

> day<-as.Date("20110701",format="%Y%m%d")
> filename(day)
[1] "20110701.csv"

4. 单元测试

编写单元测试代码


~ mkdir /home/conan/R/chinaWeather/inst/tests
~ vi /home/conan/R/chinaWeather/inst/tests/test.chinaWeather.R

library(testthat)
context("filename: current of date")

test_that("filename is current of date", {
  daystr<-paste(format(Sys.Date(), "%Y%m%d"),".csv",sep="")
  expect_that(filename(), equals(daystr))

  day<-as.Date("20110701",format="%Y%m%d")
  expect_that(filename(day), equals("20110701.csv"))
})

运行单元测试


#单个文件的单元测试
> source("/home/conan/R/chinaWeather/inst/tests/test.chinaWeather.R")
> test_file("/home/conan/R/chinaWeather/inst/tests/test.chinaWeather.R")
filename: current of date : ..

#对目录下所有文件的单元测试
> test_dir("/home/conan/R/chinaWeather/inst/tests/",reporter = "summary")
filename: current of date : ..

#自动单元测试
> src<-"/home/conan/R/chinaWeather/R/"
> test<-"/home/conan/R/chinaWeather/inst/tests/"
> auto_test(src,test)
filename: current of date : ..

#对package执行测试
> test("/home/conan/R/chinaWeather")
Testing chinaWeather
Loading chinaWeather
filename: current of date : ..

完成单元测试!下面开始撰写文档。

5. 撰写文档

这里撰写文档,使用源代码注释的方式,然后生成latex,再生成doc。比起原始的直接写latex要容易的多。

打开源代码文件:chinaWeather.R


~ vi /home/conan/R/chinaWeather/R/chinaWeather.R

#' Define a filename from current date.
#'
#' @param date input a date type
#' @return character a file name
#' @keywords filename 
#' @export
#' @examples
#' filename()
#' filename(as.Date("20110701",format="%Y%m%d"))
filename<-function(date=Sys.time()){
  paste(format(date, "%Y%m%d"),".csv",sep="")
}

生成latex文档


> library(roxygen2)
Loading required package: digest

> roxygenize("/home/conan/R/chinaWeather")
Updating collate directive in  /home/conan/R/chinaWeather/DESCRIPTION
Updating namespace directives
Writing chinaWeather.Rd
Writing filename.Rd

查看生成的latex文件


~ cat /home/conan/R/chinaWeather/man/filename.Rd

\name{filename}
\alias{filename}
\title{Define a filename from current date.}
\usage{
  filename(date = Sys.time())
}
\arguments{
  \item{date}{input a date type}
}
\value{
  character a file name
}
\description{
  Define a filename from current date.
}
\examples{
filename()
filename(as.Date("20110701",format="\%Y\%m\%d"))
}
\keyword{filename}

6. 程序打包

详细的打包解释,请参考:开发自己的R包sayHello

对上面程序过程,更简化操作可以用如下3条命令


> load_all("/home/conan/R/chinaWeather")
> test("/home/conan/R/chinaWeather")
> document("/home/conan/R/chinaWeather")

程序检查


> check("/home/conan/R/chinaWeather")
Updating chinaWeather documentation
Loading chinaWeather
'/usr/lib/R/bin/R' --vanilla CMD build '/home/conan/R/chinaWeather'  \
  --no-manual --no-resave-data

* checking for file '/home/conan/R/chinaWeather/DESCRIPTION' ... OK
* preparing 'chinaWeather':
* checking DESCRIPTION meta-information ... OK
* checking for LF line-endings in source and make files
* checking for empty or unneeded directories
* building 'chinaWeather_0.1.tar.gz'

'/usr/lib/R/bin/R' --vanilla CMD check  \
  '/tmp/RtmpM5NdJp/chinaWeather_0.1.tar.gz' --timings

* using log directory '/tmp/RtmpM5NdJp/chinaWeather.Rcheck'
* using R version 3.0.1 (2013-05-16)
* using platform: x86_64-pc-linux-gnu (64-bit)
* using session charset: ASCII
* checking for file 'chinaWeather/DESCRIPTION' ... OK
* checking extension type ... Package
* this is package 'chinaWeather' version '0.1'
* checking package namespace information ... OK
* checking package dependencies ... OK
* checking if this is a source package ... OK
* checking if there is a namespace ... OK
* checking for executable files ... OK
* checking for hidden files and directories ... OK
* checking for portable file names ... OK
* checking for sufficient/correct file permissions ... OK
* checking whether package 'chinaWeather' can be installed ... OK
* checking installed package size ... OK
* checking package directory ... OK
* checking DESCRIPTION meta-information ... OK
* checking top-level files ... OK
* checking for left-over files ... OK
* checking index information ... OK
* checking package subdirectories ... OK
* checking R files for non-ASCII characters ... OK
* checking R files for syntax errors ... OK
* checking whether the package can be loaded ... OK
* checking whether the package can be loaded with stated dependencies ... OK
* checking whether the package can be unloaded cleanly ... OK
* checking whether the namespace can be loaded with stated dependencies ... OK
* checking whether the namespace can be unloaded cleanly ... OK
* checking loading without being on the library search path ... OK
* checking for unstated dependencies in R code ... OK
* checking S3 generic/method consistency ... OK
* checking replacement functions ... OK
* checking foreign function calls ... OK
* checking R code for possible problems ... OK
* checking Rd files ... OK
* checking Rd metadata ... OK
* checking Rd cross-references ... OK
* checking for missing documentation entries ... OK
* checking for code/documentation mismatches ... OK
* checking Rd \usage sections ... OK
* checking Rd contents ... OK
* checking for unstated dependencies in examples ... OK
* checking examples ... OK
* checking PDF version of manual ... OK

Checking chinaWeather with devtools
Checking for any extra files in built .tar.gz file... OK

查检通过.
注:请安装

sudo apt-get install texlive-full

7. 程序发布

我们把写的程序发布到github上面,然后通过devtools,我可以方便的把程序从github下载安装。

在github创建一个新的资源库:chinaWeather
https://github.com/bsspirit/chinaWeather

提交本地代码到github


~ cd /home/conan/R/chinaWeather
~ git init
~ git add .
~ git commit -m 'init commit'
~ git remote add origin https://github.com/bsspirit/chinaWeather
~ git push -u origin master

To https://github.com/bsspirit/chinaWeather
 * [new branch]      master -> master
Branch master set up to track remote branch master from origin.

通过devtools下载,并安装代码。
现在我的chinaWeather包,已经在github上面发布了,如果其他的同学想使用可以下面命令安装。


> library(devtools)
> install_github("chinaWeather","bsspirit")
Installing github repo(s) chinaWeather/master from bsspirit
Downloading chinaWeather.zip from https://github.com/bsspirit/chinaWeather/archive/master.zip
Installing package from /tmp/RtmpSaXYcA/chinaWeather.zip
Installing chinaWeather
'/usr/lib/R/bin/R' --vanilla CMD INSTALL  \
  '/tmp/RtmpSaXYcA/chinaWeather-master'  \
  --library='/home/conan/R/x86_64-pc-linux-gnu-library/3.0'  \
  --with-keep.source --install-tests

* installing *source* package 'chinaWeather' ...
** R
** inst
** preparing package for lazy loading
** help
*** installing help indices
** building package indices
** testing if installed package can be loaded
* DONE (chinaWeather)

#测试包
> library(chinaWeather)
> filename()
[1] "20130805.csv"

#查看文档
> ?filename
filename             package:chinaWeather              R Documentation
Define a filename from current date.
Description:
     Define a filename from current date.
Usage:
       filename(date = Sys.time())
Arguments:
    date: input a date type
Value:
     character a file name
Examples:
     filename()
     filename(as.Date("20110701",format="%Y%m%d"))

我们完成了,开发R包的全部流程。依赖于devtools, roxygen2, testthat三个包,真是事半功倍,比起完全手动操作提高效率了很多!!

希望更多的朋友,可以站在巨人的肩膀前行,创造让人惊叹的成果来!!

转载请注明出处:
http://blog.fens.me/r-package-faster/

打赏作者

This entry was posted in R语言实践

0 0 votes
Article Rating
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

32 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
xiaofeng.0007

您好,有些问题请教:1,为什么要传到github,然后又下载下来?2,除了这个流程还有没有更详细的资料呢?现在是知道怎么做,但是不知道为什么要这样做啊!谢谢!邮箱:xiaofeng.0007@gmail.com

Conan Zhang

1. github可以方便的管理代码.

2. 对于开发者来说,你要想发布自己的包,要放到CRAN上面,这是个慢长和复杂的过程。对于R的用户来说,可以直接从github下载你的包。简化了发布过程,你不觉得很方便么。

3. 这个流程是目前我知道的最方便的流程了。如果提交到CRAN,代码规范,包结构, 都去google吧,都有答案的。

xiaofeng.0007

谢谢,在linux上做了一遍,最后还是遇到个问题:为什么library后用不了?但是查看?filename却有结果呢?百思不得其解,check都没问题的,难道是build时有问题?

Conan Zhang

你下载的是最新的版本吗?

你这个问题,一般是NAMESPACE文件中,没有写export(filename)造成的。

参考项目地址
https://github.com/bsspirit/chinaWeather

xiaofeng.0007

谢谢,一针见血啊,已经可以运行!不过又有新的问题了,再次麻烦你了:1,什么时候用S3method()?是因为默认的methods不行?对于methods概念比较模糊。2,useDynLib作用是载入共享对象?为什么么不可以用import()?3,最开始构建工程的时候为什么么用create(),这个相比于package.skeleton()好像没有什么优势啊?4,关于Hadley Wickham打包的文章一直没找到,能发个链接?

Conan Zhang

1. S3和S4,建议自己构造的对象都用S4的。S3是遗留的问题。目前,这方面的介绍文章很少。

有两个官方文档需要自己阅读:
Writing R Extensions
Building Packages in R

2. useDynLib,主要用于加载其他语言的动态库。比如像rJava需要加载jri.dll(jri.so)

3. devtools是为了简化R包开发流程的工具包。如果你用这个包,最好按照他规定的流程去开发。他规定的这个流程,我们没必要打破,再画轮造车。

4. package.skeleton()仅仅是生成几个文件,没有对开发流程做任何的标准化。自己也可以创建这几个文件。完全没什么用。

5. Hadley Wickham的文章,都出自devtools这个项目,我写的博客,大部分是基于自己的体会,没有任何翻译。
https://github.com/hadley/devtools

xiaofeng.0007

谢谢大神的耐心指导!真心感谢,谢谢!!希望在CRAN上能早日看到您的包!

Conan Zhang

🙂

xiaofeng.0007

没找到转载的按钮啊?怎么转载你这篇文章?

Conan Zhang

没有转载按钮,如果转载就是复制+粘贴。

xiaofeng.0007

嗯,好的,你的文章写得非常好,希望能够转载,不过复制+粘贴后排版有点问题!

xiaofeng.0007

你好,如果R包依赖的不是其它R包,而是网络上的软件怎么办?是不是要configuration,还是只要在SystemRequirements说明就可以呢?

Conan Zhang

这个情况,我不太清楚。

你可参考一下谢益挥的animation包的实现写法。
animation::saveGIF需要依赖于ImageMagick或者GraphicsMagick。

xiaofeng.0007

谢大的包需要用户自行安装。我想自动安装的,昨天找到了个包也可以实现类似的功能。但是尝试了很久都不知道怎么自动加载那个依赖包,Depends和import都不行啊!

Conan Zhang

自动安装,估计R语言很难实现吧,是不是对R语言要求太高了。

xiaofeng.0007

这个应该是有的,要不然开发出来的R包有依赖关系的话,不就不能用了?我以前加载的包,可没有手动去下载那依赖包的!

xiaofeng.0007

发现原因了,之前是我这边有点问题。只要在Depends中说明,install后library()就会自动加载依赖包。。

Conan Zhang

依赖R包,在Depends配置好就行了。

我以为你是想自动安装第三方软件呢,”网络上的软件”!

xiaofeng.0007

之前在51cto上看到一篇报道:“2014最值得学习的语言—必须是R”。应该是您的杰作吧,写得很精辟!!让我对R充满信心啊!

Conan Zhang

过奖了,学好R是很有用的。

xiaofeng.0007

又来麻烦下你了,请部下:打包后有什么好方法进行调试吗?我是重新加载原代码来调试的,比较麻烦。可不可加载R包后,也可以进去调试呢?

Conan Zhang

似乎没有什么其他方法,只能通过源代码的方式调试。

xiaofeng.0007

好的,谢谢!晚安……

xiaofeng.0007

在linux下怎么打包成zip格式?
R CMD INSTALL –build test.tar.gz和R CMD build –binary test都不行啊???

Conan Zhang

我不记得是否支持打包到zip,通用的是tar.gz;等我有时间时,再查一下。

xiaofeng.0007

好的,谢了!

[…] R包开发编程:开发自己的R包sayHello, 在巨人的肩膀前行 催化R包开发 […]

[…] devtools的详细安装说明和使用,请参考文章:在巨人的肩膀前行 催化R包开发 […]

[…] R语言性能可视化lineprof | 粉丝日志 on 在巨人的肩膀前行 催化R包开发 […]

xiaoxiao feng

你好。如果要把用R做的模型打包怎么办呢?我现在是把模型保存成RData格式的文件,每次load一下这个文件,如果打包该怎么处理呢?谢谢

Conan Zhang

打包时,把数据文件变成 *.rda 的格式,用户library包时,会自动装载这些数据。

参考这篇文章中的实现
http://blog.fens.me/r-package-chinaweather/

[…] 如果想要安装开发版本,可以使用devtools来进行安装,devtools的介绍请参考文章:在巨人的肩膀前行 催化R包开发 […]

32
0
Would love your thoughts, please comment.x
()
x