之前我说过要做一个包,说到做到的,所以已经开始弄,也顺便写几篇文章。
开发理念
任何能够自动化的东西,都尽量让其自动化
准备工作
- 包开发必备的包
install.packages(c("devtools","roxygen2","testthat","knitr"))
2.检查开发环境是否最新
install.packages('rstudioapi')
> rstudioapi::isAvailable('0.99.149')
[1] TRUE
TRUE表示开发环境是ok的
- 检查是否所有工具都安装了
devtools::has_devel()
'/usr/lib64/R/bin/R' --no-site-file --no-environ --no-save --no-restore \
--quiet CMD SHLIB foo.c
gcc -m64 -std=gnu99 -I"/usr/include/R" -DNDEBUG -I/usr/local/include -fpic -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -c foo.c -o foo.o
gcc -m64 -std=gnu99 -shared -L/usr/lib64/R/lib -Wl,-z,relro -o foo.so foo.o -L/usr/lib64/R/lib -lR
[1] TRUE
>
TRUE表示ok的
包的结构
-
命名
-
创建一个包
使用Rstudio,新建一个项目:
image.png
然后点击New Directory
image.png
点击R Packages
image.png
或者可以在R中通过命令来输入创建一个包:
devtools::create('path/to/package/pkname')
结构是会产生一个最小的可用包,有三个部分组成
- 一个R/目录
- 一个描述文件DESCRIPTION
- 一个命名空间的文件NAMESPACE
开发一个包的时候,所有的R代码都需要放在一个R/目录里面
组织函数
不要把函数全部放倒一个文件里面,并且函数的名字最好要有意义。
顶层代码
使用source
可以运行一个脚本里面的所有代码,但是脚本的代码和包的代码有两个主要区别
- 脚本是被加载的时候运行,包是在被编译的时候运行,意味着你的包只创建对象,而对象的大部分内容应该是函数。
- 包可能会被应用到你没有想象过的环境,意味着你要小心处理其与调用者的关系。
使用source
加载脚本的时候,每一行代码都会执行,且执行的结果可以立即使用。对包而言,情况有所不一样,其加载分为两步,包被编译的时候,R/
目录下的所有代码都会被执行,结果会被保存下来。当用library
的时候,这些保存的结构可以使用了.
这意味着你不能在包的顶层运行代码:包的代码只能是创建对象,主要是函数。
例如你的包含有这样的代码fristpk
library(ggplot2)
show_mtcars=function(){
qplot(mpg,wt,mtcars)
}
如果有人试图这样运行
library(fristpk)
show_mtcars()
代码不会工作,因为ggplot2
的qplot
函数不可用,library(fristpk)不会重新执行library(ggplot2)
包的顶层代码只有在包编译的时候运行, 你可以这样修改
show_mtcars=function(){
library(ggplot2)
qplot(mpg,wt,mtcars)
}
R运行环境
如果使用library加载了一个包,options修改了一个全局设置,或者用setwd修改了工作目录,你已经修改了工作环境了,这样代码会很难阅读,因此修改运行环境是很不友好的一种行为。
永远不要用一些修改全局设置的函数
- 不要使用librry,使用require
- 不要使用source从文件中加载代码
- 如果你要修改全局的options或者图形的par,先把旧的设置保存下来,然后在你用完之后恢复到原来的值。
- 创建图和输出到控制台是另外两种影响R全局环境的方式,通常无法避免,最好的做法是将输出功能做成独立的函数
包的代码有几点注意事项:
- 所有的代码写在R/里面
- 包主要创建对象,函数
- 不要修改全局设置
网友评论