美文网首页R统计编程
R语言 -- 如何制作自己的R包 详细示范

R语言 -- 如何制作自己的R包 详细示范

作者: 生信摆渡 | 来源:发表于2023-03-30 16:08 被阅读0次

前言

为什么要写包?不用多解释了:

  • 载入并调用你编写的函数,而不是全放到环境里
  • 方便管理
  • 发布 CRAN/Bioconductor !

一年前写了一个超简单的教程:编写你自己的R包 - 简书 (jianshu.com),但仅介绍了如何把单个函数写进包里。先看下这个简单的教程会理解本文有很大帮助。

今天来个进阶版,把你function.R里所有的函数都写进包里,甚至多个脚本里的函数也支持。

开始制作

建议在Rstudio里操作。

依赖的包

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

一些预设

rm(list = ls()) 
pkgName = "efficeintR"
version = "1.0.0"
author = "Jiahao Wang"
masterDir = "D:/03_Study/R_build"
funDir = "D:/02_Software/R-4.2.1/library/base/R/yyds"
  • masterDir:主目录,在这下面去制作一些包
  • funDir:函数目录,里面是一个或多个包含函数的脚本

起始R包

require("devtools")
dir.create(paste0(masterDir, "/", pkgName), recursive = TRUE)
create_package(paste0(masterDir, "/", pkgName, "/", pkgName))

运行后会单独打开一个Rstudio界面,自动进入R包目录。


重新运行预设:

pkgName = "efficeintR"
version = "1.0.0"
author = "Jiahao Wang"
masterDir = "D:/03_Study/R_build"
funDir = "D:/02_Software/R-4.2.1/library/base/R/yyds"

首先,修改包的描述信息,打开右侧文件栏中的DESCRIPTION,简单编辑一下版本、标题、作者、描述等:

一键导入函数

这里我写了一个函数可以一键将包含函数的若干R文件导入到包内:

buildFuns <- function(funFile, author){
   funOut = paste0("R/", basename(funFile))
   sink(funOut)
   Lines = readLines(funFile)  
   for(i in 1:length(Lines)){
       Line = Lines[i]
       if(grepl("<- function", Line)){
           if(! subString(Line, 1) %in% c("#", "\t", " ")){
               funName = subString(Line, 1, " ")
               cat("#' @title", funName, "\n")
               cat("#' @author", author, "\n")
               cat("#' @export\n")
           }
       }
       cat(Line, "\n")
   }
   sink()
}
  • 其实就是逐行写入包中,需要增加的就是函数头的一些内容。
    • 注意,这里的写入有一定的规则,大家可能需要按自己的习惯去调整:
    • 编写函数时使用funName <- function(paras)格式,这样就能被识别到该行是声明一个新函数
    • 从而,在该行之前插入函数的头信息,这里仅包括:函数名、作者、导出该函数,详细的帮助文档也可自己手动加入,下文有示例
    • 对于一些函数内函数和被注释掉的函数,不给予处理

一键导入函数:

funFiles = list.files("D:/02_Software/R-4.2.1/library/base/R/yyds", ".R$", recursive = TRUE, full.names = TRUE)
sapply(funFiles, buildFuns, author)

点开R文件夹,就会发现函数已经部署到这里了:

打开check.R康康:

细化帮助文档

每个函数的帮助文档各不相同,只能单个去编辑了,这个是最费时间精力的了

如果暂时只是自己使用,可以这一步略过

但为了教学,那就演示一下函数帮助文档的编写吧

编辑方式就是直接打开上面生成的脚本,对你想要编辑的函数按以下格式编写:

#' Enhanced version of 'head'.
#' Default only print 5x5 field for two-dimensional data
#' or first 5 element for one-dimension data.
#' And print dimension of data in first line.
#' It also support specified range.
#' Don't worry about going out of range, it can fix it!
#' 
#' 
#' @title hd
#' @param obj data object.
#' @param x Number to print of horizontal direction, defaut 5.
#' @param y Number to print of vertical direction, defaut 5.
#' @author Jiahao Wang
#' @examples
#' hd(LETTERS, 10)
#' hd(LETTERS, 24:100)
#' df = get(data(package = "ggplot2", "diamonds"))
#' rownames(df) = paste0("row_", 1:nrow(df))
#' colnames(df) = paste0("col_", 1:ncol(df))
#' hd(df)
#' hd(df, 3, 5)
#' hd(df, 3:5, 7:9)
#' hd(df, -10:-nrow(df), -3:-5)
#' hd(df, (nrow(df) - 2):10^6, (ncol(df) - 2):10^6)
#' @return A part of input data.
#' @export
hd <- function(obj, x = 5, y = NULL){

    check_len <- function(idx, max){
        if(length(idx) > 1){
            if(max(idx) > max){
                idx_res = idx[idx <= max]
            }else{
                idx_res = idx
            }
        }else{
            if(idx > max){
                idx_res = 1:max
            }else{
                idx_res = 1:idx
            }
        }
        return(idx_res)
    }

    if(is.null(y))
        y = x

    dims = is.null(dim(obj))
    if(!dims){

        cat("dim:", nrow(obj), "×", ncol(obj), "\n")

        idx_x = check_len(x, nrow(obj))
        idx_y = check_len(y, ncol(obj))
        res = data.frame(obj[idx_x, idx_y])
        if(!is.null(rownames(obj)))
            rownames(res) = rownames(obj)[idx_x]
        if(!is.null(colnames(obj)))
            colnames(res) = colnames(obj)[idx_y]
    } else{
        cat("dim:", length(obj), "\n")
        idx_x = check_len(x, length(obj))
        res = obj[idx_x]
        if(!is.null(names(obj)))
            names(res) = names(obj)[idx_x]
    }
    return(res)
}

看起来就是这样:

函数部分不用改动。

校验

为了生成R包,我们还需要进行格式校验、Rmd生成这两部,也是一键完成:

check()
document()

check的运行结果没用error就没问题,因为前面没用写依赖的包,所有提示了很多无法在当前环境找到该函数的定义之类的信息,以后再解决这个问题。不影响使用,只是如果没用安装依赖包的话有些函数载入包时会提示报错。

生成并安装R包

setwd("../")
system(paste("Rcmd build", pkgName))
install_local(paste0(pkgName, "_", version, ".tar.gz"))

一切正常:

载入测试

library(efficeintR)

# 查看包介绍
packageDescription("efficeintR")

# 查看可用函数
ls("package:efficeintR")
  • 看看刚才编写的hd函数:
    ?hd

有详细的文档说明

而没有编辑详细文档的:

?runWGCNA

共享

直接分享压缩包或者上次到github使用devtools::install_github()安装即可。


至此,一份香喷喷的R包制作完成~(品诺王语气

相关文章

  • Day6—刘强

    R语言之R包概述 What's R package? R包是多个函数的集合,具有详细的说明和示例学生信,R语言必学...

  • 学习小组Day6笔记-Bonnie

    学习R包 R包是多个函数的集合,具有详细的说明和示例。学生信,R语言必学的原因是丰富的图表和Biocductor上...

  • R语言学习记录

    如何理解AUC R语言 apply函数家族详解 R语言资料从Github上安装R包 Windows下使用insta...

  • R语言:highcharter包绘制可交互的高级图表(一)

    本期介绍在R语言如何使用highcharter包绘制可交互的高级图表,highcharter包是R语言中绘制Hig...

  • R语言:highcharter包绘制可交互的高级图表(二)

    本期介绍在R语言如何使用highcharter包绘制可交互的高级图表,highcharter包是R语言中绘制Hig...

  • 2019-02-19

    R语言学习笔记-R包安装 R语言是一个开放性的统计学语言,r包的丰富程度涵盖了几乎生产和生活的各个方面,r包与r包...

  • 关于加载本地版R包的基因教训

    加载本地R包对于大部分R语言初学是一个难题,今天我们来聊一聊如何正确的安装离线R包。 GEOmirror R包是从...

  • 2020-10-14 入门小组DAY6-三三

    学习R包——以dplyr为例 R包是多个函数的集合,具有详细的说明和示例。学生信,R语言必学的原因是丰富的图表和B...

  • R包:如何安装R包

    介绍 R语言提供的大量R包为众多研究者提供了足够的工具,但是如何安装R包是很多人在使用R语言做数据分析时候所面临的...

  • 《R语言实战》day 1

    第一章 R语言介绍 本章学习:R的安装/Rstudio安装-- 熟悉R语言--运行R程序 1.安装R的详细教程 (...

网友评论

    本文标题:R语言 -- 如何制作自己的R包 详细示范

    本文链接:https://www.haomeiwen.com/subject/iiaqddtx.html