R package

简单来讲的话,R package 其实就是把代码函数,数据和文档打包起来的一个文件夹。最近统计软件课上学习了R包的结构、创建,这里是一篇总结文。我的课堂作业R包传上了github主页,可以devtools::install_github("yangggshuyi/yang88") 安装使用哟!

什么是 R包

简单来讲的话,R package 其实就是把代码函数,数据和文档打包起来的一个文件夹哈哈哈哈。通常我们讲R包,包括源码和编译之后的版本,源码大多是R语言写的(当然可以用上其他语言)。如果这个包没有编译过,在安装的时候会编译之后装。

想要安装R包,按照来源可以分为本地、github、cran。CRAN是包含R发行版和已贡献代码(尤其是R包)的网络,从cran上任意点进去一个包的主页,比如glmnet包,可以看到如下信息(还没看到源码,先看到复杂的介绍文档和论文了可怕):

简单写个函数不难,但是如何包装,如何从使用者的角度考虑进行完善,包括如何写帮助文档,这些琐碎的事情有时候劳心费神。就拿写help来说,有些help文档真的看不大懂有些一下就能明白。从使用者的角度来看,好的文档应该解释清楚参数的含义、得给出有用的示例代码等等,如果真的要做R包,除了code还要干很多活呐。

R包的结构

一个简单的包结构

创建R包前先看看R包(一个大文件夹)里面具体有哪些内容。一个简单的包结构是这样子的:

|--DESCRIPTION (软件包的基本信息,包括包名、版本号、标题、描述、依赖关系等)
|--R (函数源文件)
   |--function1.R
   |--function2.R
   |--...
|--man (帮助文档)
   |--function1.Rd
   |--function2.Rd
   |--...
|--data(存放数据)
   |--data1.RData
   |--data2.RData

首先注意R文件夹,这个文件夹下应该放着所有的自创的 R 代码,比如可以每个函数一个文件,方便整理。而每一个函数其实都有对应的输入变量和数据结构,应该有对应的解释等。在 man 文件夹中会有对应的 .Rd 文件,里面的内容看起来是latex,就是我们每个函数的help文档内容。

课堂上我们直接对 .Rd 文件进行修改,其实并不方便&不大合理。除了直接修改,常见的办法就是在R文件函数上面加上一串注释。这种注释是 #' 开头的,会由 devtools 里面的辅助函数来进行处理,大概长这样:

#' title
#' This function...
#' @param abc ...   
#' @export
#' @examples

这样写完你的help文档之后,运行document(),会自动生成对应的 *.Rd 文件在 man 文件夹中(似乎变得简单了起来)

进阶R包的结构:

(这里用glmnet包为例,瞅瞅它的源码是这样的:

除了 R 和 man 文件夹之外,还有一些可能有用的东西/文件夹

  1. demo
    下面可以放一些演示 R 代码,这样用户可以使用demo()函数调用这些演示
  2. data
    放数据,通常是通过save()函数保存成 rda 文件放到这里
  3. src
    可以放其它语言的源代码,编译时会特殊处理;
  4. Vignette
    关于一个包的介绍文档,里面是rmarkdown & html
  5. NAMESPACE
    可以控制哪些 R 对象是对用户可见的,哪些对象是从别的包导入(import),哪些对象从本包导出(export)。比如有些函数仅仅供你自己使用,对用户没什么帮助,就可以利用export(函数名)只导出那些需要对用户可见的函数。

R包的建立和发布

了解了这些,创建和发布可以用点点点的无脑操作完成。

  • 第一步:创建
    创建一个new project,选择 R package,会生成一个大文件夹,点击文件夹里的蓝色Rproj图标就进入这个project啦!
  • 第二步:添加
    往文件夹里添加我们想要添加的内容,函数、文档、数据等等
  • 第三步:打包
    点build创建我们的R包

    source 是源码, binary是编译过的(分为windows和mac两个版本),一般还是 build source R包方面系统互通。
  • 第四步:发布和适用
    这里我试了下发布在github上面,建一个同名库之后把源码文件夹全部放上去就好了,非常简单哈哈。安装放在github上的R包可以这样:(欢迎安装使用我的包嘻嘻)
devtools::install_github("yangggshuyi/yang88")
library(yang88)

那如果没有上传,直接本地安装也是可以滴:

install.packages("~/yang88_0.1.0.tar.gz", repos = NULL, type = "source")
library(yang88)