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 种常用的函数:标准函数、闭包、中缀操作符和替换函数
标准函数
标准函数由 3 个部分组成:函数名、参数和函数体,使用 function()函数来创建。
其中参数可以设定默认值,其中参数取值可以设限,比如性别取值男和女,在构建函数时,最好将所有取值列出,并使用 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