R包构建

R语言中R包构建流程

Posted by CHY on July 8, 2020

R 语言是生物信息必备的技能,其中 R 包更是 R 语言的核心,尤其是在发表相关的生信文章时,一个 R 包的提出更是文章投稿成功的关键。所以在此特异学习一下 R 包的开发。

工具

R 软件、RStudio 软件、Rtools 软件、devtools 包、roxygen2 包
值得一提的是,Rtools 是 Windows 下的软件,并不是一个 R 包,一般在安装 Rstudio 时会自动的安装 Rtools.

R 包命名规则

  • 必须以字母开头(大写或小写),如:ggplot2,不能写成 2ggplot
  • 只能包含字母(大写或小写),数字和点,如:covid19.analytics
  • 不能和已有的包名称冲突,已有的包指 CRAN 和 bioconductor 上的包

创建 R 包

setwd("F:\\R-package") # 进入创建的R包目录,目录不要有中文
library(devtools)
create_package("fpkg")  # 会自动打开新的界面
# 会在文件夹中自动生成下面的文件或文件夹
# .Rproj.user文件夹:RStudio的项目文件夹,不需要关注
# R文件夹:存放R代码文件夹,重要***
# .gitignore文件:存放git信息的文件,会被忽略
# DESCRIPTION文件:R包的说明文档,这是整个包的说明文档,重要***
# fpkg.Rproj文件:RStudio的项目文件,我们以后编辑R包的时候,都是通过打开它来编辑的,因为这个文件包含了创建R包的菜单,重要**
# NAMESPACE文件:存放R包函数命名空间的文件,不需要手动编辑,极其重要*

R 包中可以包含很多文件夹,不同的文件功能不同,常用的有 R 文件夹、Data 文件夹和 vignette 文件夹。

  • R 文件夹是存放代码的地方,也就是我们所有的 R 代码
  • Data 文件夹不像 R 文件夹会自动产生,你可以使用函数 use_data()来添加 R 数据,也可以手动新建,在后面的章节中会详细讲解如何添加数据
  • vignette 文件夹是用来添加 markdown 格式的说明文档,可以使用函数 use_vignette()来创建,需要注意的是,如果你要添加 vignette 文件夹,需要安装 knitr 包、rmarkdowan 包和 pandoc。前 2 者的安装可以使用命令 install.packages()来安装即可

R 包内的文件夹不支持二级目录,也就是 R 文件夹下不能再有下一级目录

封装包

# Rstudio中命令封装
1. 双击文件目录中的fpkg.Rproj
2. 通过Build菜单封装包
3. 单击Build菜单下的Document项(更新文档,更新roxygen版本的文档,载入fpkg包,最后完成更新)
4. 建包,使用build菜单下的Install and Restart或者Clean and Rebuild均可,选择任意一个单击即可
# 快捷键封装
写入注释:Ctrl/Command + Shift + D
建包:Ctrl/Command + Shift + B
# 命令封装
devtools::document()
devtools::build()

创建函数

R 中有 4 种常用的函数:标准函数、闭包、中缀操作符和替换函数 R中函数类型

标准函数

标准函数由 3 个部分组成:函数名、参数和函数体,使用 function()函数来创建。 R中标准函数 其中参数可以设定默认值,其中参数取值可以设限,比如性别取值男和女,在构建函数时,最好将所有取值列出,并使用 match.arg()进行匹配。

return_sex <- function(sex = c('男', '女')){
   sex=match.arg(arg = sex,
   choices = c('男','女'))
   return(sex)
}
# 给出以外的值会报错

三连点用于不设定参数的个数。任意多个参数均可。
return()的作用是返回数值,并且中断函数。

闭包

闭包区别于标准函数的地方在于闭包没有函数名。也就是说闭包是一个无名函数,仅仅包含了参数和函数体。

中缀函数

中缀函数的结构类似于夹心饼干,两边 2 个百分号%,中间是它的函数名。

`%sum%`<- function(a, b) a + b  # 反引号
'%sum%'<- function(a, b) a + b  # 单引号
"%sum%"<- function(a, b) a + b  # 双引号

环境

内容—>对象(一个或多个,相当于 word 文本)—>环境(相当于文件夹)

# 查看当前活动环境
environment()
# 创建新的环境
new.env()
# 环境赋值
# assign(对象,内容,环境)
assign()
View(e)

环境是 R 管理和存储各种数据的地方,每一个函数在创建之初都会创建自己的环境。
R 中环境的另外一个特点:单向:全局环境(父环境)中的数据可以传入它的局部环境(子环境)中,而局部环境中的数据不可以传入全局环境中,如果想将局部环境中的变量传入全局环境中,需要使用全局赋值符号«-。

函数注释

菜单插入

将光标定位在函数内部,然后依次点击菜单栏的 Code、Insert Roxygen Skeleton,就插入了注释框架。

快捷键插入

将光标定位在函数内部,然后使用快捷键 Ctrl+Alt+Shift+R 即可插入。

@title  指定标题
@description 描述部分必须是1整个段落,这意味着必须以句号也就是点来结尾。如果内容多,可以换行,每行最好不要超过80个字符,并且换行后要以4个空格开头。
@param 后空1格,写参数的名称,再空1格,写参数的解释,参数的解释不能为空。code{link[pkg]{rdname}}中,pkg等于base,rdname等于sum,也就是写成code{link[base]{sum}},链接说明文档。
@return 说明函数的返回内容。
@export 导出函数,函数仅仅在包内使用,那么就不需要添加@export,删除即可。
@importFrom 引用其他包中函数,写法是@importFrom+包名+函数名(一个或多个)

R 包实例学习

虽然前面介绍了很多关于R包开发需要注意的事情,但是具体的熟悉运用还是需要通过实例重写来加深印象。

第一个简单实例:sceasy包学习

sceasy是一个转换单细胞数据格式的R包,总体函数只有三个,是入门R包的必备材料。

library(devtools)
create_package("SCC")   # 创建R包
use_r("functions")   # 创建函数文件

devtools::load_all()   # 载入创建的函数

usethis::use_mit_license("aa bb")  # 修改R包权限问题
converFormat <- function(
  obj, from = c('anndata','seurat','sce','loom'), to = c('anndata','loom','sce','seurat'), outFile = NULL,
  main_layer = NULL, ...
){
  from <- match.arg(from)    # 匹配参数
  to <- match.arg(to)

  tryCatch({
    func <- eval(parse(text = paste(from,to,sep = "2")))    # parse()函数能将字符串转换为表达式expression;eval()函数能对表达式求解
  },error = function(e){
    stop(paste0('Unsupported conversion from "',from,'" to "',to,'"'),call. = FALSE)  # stop停止执行当前表达式并执行一个错误的行动
  },finally = {})

  return(func(obj,outFile = outFile, main_layer = main_layer, ...))
}

# stop(..., call. = TRUE, domain = NULL)   错误
# warning(..., call. = TRUE, immediate. = FALSE, noBreaks. = FALSE, domain = NULL)     警告
# message(..., domain = NULL, appendLF = TRUE)     提示

R 包干货奉献
把函数包起来就是一个R包 - 完整开发指南
在Rstudio中点一点就出来了一个R包
在巨人的肩膀前行 催化R包开发
极简 R 包建立方法
如何快速写一个R包
R_package_development_introduction