R包开发

R包开发系统学习

Posted by CHY on November 28, 2020

R包开发书籍:https://r-pkgs.org/whole-game.html

R包开发简单流程

library(devtools)
packageVersion("devtools")
library(tidyverse)      # 数据轻量级处理
library(fs)        # 文件系统处理

create_package("F:\\R-packages\\foofactors")  # 通过双击foofactors.Rproj进入开发界面

use_git()   # 使开发包成为一个git库

dir_info(all = TRUE, regexp = "^[.]git$") %>%  # 查找文件夹
  select(path, type)

use_r()   # 在开发包中创建一个R脚本存储函数
load_all()  # 加载新创建的函数到环境中

check()   # 检查函数的可靠性

use_mit_license("Hongyu Chen")    # 设置R包服从的协议

# 在使用roxygen2包后需要先运行document()函数,最后会生成man文件夹

R包开发前期准备

install.packages(c("devtools", "roxygen2", "testthat", "knitr"))

R包-DESCRIPTION部分

##### 依赖
# Imports标注必须安装的包
# Suggests标注非必须的包
# 添加Imports和Suggests最简单的方法是使用devtools::use_package()
devtools::use_package("dplyr") # 默认为imports

# 指定特定的版本
Imports:
    ggvis (>= 0.2),
    dplyr (>= 0.3.0.1)
Suggests:
    MASS (>= 7.3.0)

# 指定需要的R版本--Depends
devtools::create()

# LinkingTo  列出包依赖于另一个包中的 C或C++代码
# Enhances 不建议使用
#### 标题和描述
Description部分可以为多个句子,但从第二行开始需要增加四个空格,其次每行不能超过80个字符

#### 作者 -- Author@R
Authors@R: person("Hadley", "Wickham", email = "hadley@rstudio.com",
     role = c("aut", "cre"))
# aut 指包的作者;cre 指包的维护者;ctb 贡献者;cph 版权所有人
Authors@R: c(
    person("Hadley", "Wickham", email = "hadley@rstudio.com", role = "cre"),
    person("Winston", "Chang", email = "winston@rstudio.com", role = "aut"))

#### 许可证
# 三种许可证:MIT、GPL-2、CC0 (权限依次升高)

#### 版本号
<主版本号><次版本号><补丁版本>

对象文档

对象文档也就相当于对包以及包中的函数进行解释,一般在R包的man目录下会存在.Rd文档

#### 文档工作流程
1. 添加roxygen注释到.R文件
2. 运行devtools::document()
3. 利用?预览文档
4. 修改注释,重复上述步骤

介绍块
@在roxygen中具有特殊意义,如果想要添加需要使用@@
@section 标签在文档中添加任意的块
@seealso 指向其他有用的资源
@family 如果有一族相关的函数,每个函数都应该链接到族中的其他函数
@aliases  增加别名
@keywords  增加标准化的关键词

函数块
@param 名字 描述
@examples 提供可执行的R代码   \dontrun{} 可以让你在实例中包括无需运行的代码
@return  返回值描述

包文档
为NULL提供文档
#' foo: A package for computating the notorious bar statistic.
#'
#' The foo package provides three categories of important functions:
#' foo, bar and baz.
#'
#' @section Foo functions:
#' The foo functions ...
#'
#' @docType package
#' @name foo
NULL
一般存在为叫作<包名>.R的文件中

长篇文档

# 查看安装包的使用指南
browseVignettes()
browseVignettes("包名“)
vignette()  # 阅读指定部分(源文件、html文件、R代码文件)

# knitr提供R Markdown使用指南引擎
# pandoc协调Markdown和knitr之间的工作,且提供较多的模板将markdown转换为html

# 创建使用指南
devtools::use_vignette("my-vignette")   # 旧版本使用
usethis::use_vignette("my_vignette")

测试

# 利用testthat进行自动化测试
devtools::use_testthat()

# 测试结构组成--期望
1. 它们以 expect_ 开始。
2. 它们有两个参数:第一个是实际结果,第二个是期望值。
3. 如果实际结果与预期不一致,testthat 将抛出一个错误。

expect_equal() 和 expect_identical()测试相等的基本方法,expect_match() 检查一个字符向量是否和一个正则表达式匹配。 expect_output() 检查打印输出; expect_message() 检查消息; expect_warning() 检查警告; expect_error() 检查错误。expect_is() 检查对象是否从指定的类 inherit() (继承)。

命名空间

命名空间以两种方式让包相对独立:Import和Export
Import 定义一个包中的函数如何找到另一个包中的函数。
Export 指定哪些函数可在包外使用(内部函数只在包内可用,并不能很容易地被另一个包使用),以此帮助你避免与其他包冲突。

R搜索路径:1.全局环境下找 2.在搜索路径中你已经??的所有包中寻找;可通过search()查看
加载与附加的区别:加载后,该包就会在内存中,但它不在搜索路径中。附加一个已加载的包会将包放在搜索路径中。
Imports 只是加载包, Depends 附加包。

永远不要在包里面使用library()

# roxygen2包生成NAMESPACE文件
# 要导出一个对象,在它的 roxygen 块中放入 @export
# 可以设置util.R文件来记录一些不需要导出的小函数

# 导入
# 如果你只是使用了其他包的几个函数,我的建议是在 DESCRIPTION 文件的 Imports 域列
出包,然后调用函数时显式地使用 ::

外部数据

• 如果你想存储二进制数据,并把它提供给用户,就把它放在 data/ 目录。这是放示例数 据集最好的地方。 • 如果你想存储解析过的数据,但不将它提供给用户,就把它放在 R/sysdata.rda。这是存 放函数所需数据的最佳场所。 • 如果你想存储原始数据,则把它放在 inst/extdata。 导出的数据也需要文档:同样使用roxygen2完成,其中@format记录数据集的概述,@source提供数据来源的细节

编译过的代码

重点使用Rcpp包,但需要重新学习C++/C的代码编写,过于复杂

devtools::use_rcpp()

安装文件

主要需要配置inst目录下的文件,主要需要增加包的引用文件;citHeader(),citEntry()

自动检查

R CMD check or devtools::check()

  1. 检查元数据
  2. 包的结构
  3. 描述
  4. 命名空间
  5. 代码
  6. 数据
  7. 文档
  8. 演示
  9. 编译过的代码
  10. 测试
  11. 使用指南