使用roxygen2记录S4方法:明确区分帮助文件中的方法

Rap*_*ter 6 methods r package s4 roxygen2

在你瞄准和射击之前

我知道这个问题与这篇文章密切相关.事实上,我遵循了各种答案中给出的建议,但仍然认为生成的帮助文件有点"尴尬"或至少看起来有点"捣碎",因此我的问题

实际问题

  1. 在记录S4泛型及其各自的方法时,如何最终得到一个Rd文件结构,让用户可以清楚地区分各种方法,使得文档的哪一部分特别属于哪种方法?
  2. 鉴于我提供了@alias标签,在尝试获取特定方法的帮助时,如何实际使用它们?有点像?foo-character-method而不只是打字?foo吗?
  3. 最好不要在通用方法中更好地记录a)签名参数,因为每个方法肯定都包含相应的文档和b)返回值,因为这也取决于相应的方法?

现在,我觉得我最终得到的帮助文件似乎无法正确区分通用和各种方法 - 至少在视觉上是这样.

但也许我还没有完全得到这个;-).在这种情况下,任何指针都将非常感谢!


这是一个可重现的示例,它生成mypkg包含S4泛型和两种方法的包.我试图遵循这篇文章中给出的建议和编写R扩展

确保目录

sapply(c("src", "package"), dir.create, showWarnings=FALSE)
Run Code Online (Sandbox Code Playgroud)

通用方法定义

gnrc.roxy <- c(
    "#' Doing Something Useful",
    "#'", 
    "#' Description here.",
    "#'", 
    "#' @param x A signature argument for method dispatch.",
    "#' @param y A signature argument for method dispatch.",
    "#' @param arg.1 A \\code{logical} scalar. If \\code{TRUE} (default)", 
    "#'      something happens; else not.",
    "#' @param arg.2 A \\code{numeric} vector containing some useful numbers.", 
    "#' @param ... Further arguments.",
    "#' @return Depends on the actual method.", 
    "#' @references \\url{http://www.rappster.de/}",
    "#' @author Janko Thyson \\email{janko.thyson@@rappster.de}",
    "#' @examples", 
    "#'   foo(x=\"a\", y=letters[1:5])",
    "#'   foo(x=\"a\", y=1:5)",
    "#' @docType methods",
    "#' @rdname foo-methods",
    "#' @export"
)    
gnrc.def <- c(
    "setGeneric(",
    "    name=\"foo\",",
    "    signature=c(\"x\", \"y\"),",
    "    def=function(",
            "x,",
            "y,",
            "arg.1=TRUE,",
            "arg.2,",
            "...",
    ") {",
    "standardGeneric(\"foo\")",       
    "})"
)
path <- "src/gnrc_foo.R"
write(gnrc.roxy, file=path)
write(gnrc.def, file=path, append=TRUE)
Run Code Online (Sandbox Code Playgroud)

相关方法的定义

mthd1.roxy <- c(
    "#' @param x A \\code{character} scalar.",
    "#' @param y A \\code{character} vector.",
    "#' @return A \\code{character} vector.", 
    "#' @docType methods",
    "#' @rdname foo-methods",
    "#' @rdname foo-methods",
    "#' @aliases foo,character,character-method",
    "#' @export"
)    
mthd1.def <- c(
    "setMethod(",
        "f=\"foo\",",
        "signature=signature(x=\"character\", y=\"character\"),", 
        "definition=function(",
            "x,",
            "y,", 
            "...",
        ") {",
        "print(x);print(y);return(y)",
        "})"
)    
path <- "src/mthds_foo.R"
write(mthd1.roxy, file=path)
write(mthd1.def, file=path, append=TRUE)

mthd2.roxy <- c(
    "#' @param x A \\code{character} scalar.",
    "#' @param y A \\code{numeric} vector.",
    "#' @return A \\code{numeric} vector.", 
    "#' @docType methods",
    "#' @rdname foo-methods",
    "#' @rdname foo-methods",
    "#' @aliases foo,character,numeric-method",
    "#' @export"
)    
mthd2.def <- c(
    "setMethod(",
        "f=\"foo\",",
        "signature=signature(x=\"character\", y=\"numeric\"),", 
        "definition=function(",
            "x,",
            "y,", 
            "...",
        ") {",
        "print(x);print(y);return(y)",
        "})"
)    
write(mthd2.roxy, file=path, append=TRUE)
write(mthd2.def, file=path, append=TRUE)

# Test source to see if methods were defined correctly
#sapply(list.files("src", full.names=TRUE), source)
Run Code Online (Sandbox Code Playgroud)

创建包骨架

# Ensure empty package directory
subdirs <- list.files("package", full.names=TRUE)
if (length(subdirs)) {
    sapply(subdirs, unlink, recursive=TRUE)
}

pkg.name    <- "mypkg"
path        <- file.path("package", pkg.name)

package.skeleton(
    name=pkg.name, 
    path="package", 
    code_files=list.files("src", full.names=TRUE, recursive=TRUE)
)
Run Code Online (Sandbox Code Playgroud)

Roxygenize

require("roxygen2")
roxygenize(package.dir=path)
Run Code Online (Sandbox Code Playgroud)

修补Rd文件

有些事情需要修补,以便允许自动检查和构建过程,不需要任何手动干预,如手动编辑Rd文件等.

rdfiles <- list.files(file.path(path, "man"), full.names=TRUE)

# 1) Removing unnecessary file './package/mypgk/man/foo.Rd'
file <- grep("foo.Rd", rdfiles, value=TRUE)
if (length(file)) {
    unlink(file)
}

# 2) Patching './mypkg/man/mypkg-package.Rd' to pass R CMD CHECK
file <- grep(paste(pkg.name, "-package.Rd", sep=""), rdfiles, value=TRUE)
if (length(file)) {
    cnt <- readLines(file, warn=FALSE)
    idx.0 <- grep("\\\\examples\\{", cnt)
    if (length(idx.0)) {
        idx.1 <- grep("\\}", cnt)
        idx.1 <- max(idx.1[which(idx.1 > idx.0)])
        exnew <- c(
            "\\examples{",
            "# TODO: add examples",
            "}"
        )
        cnt <- cnt[-(idx.0:idx.1)]
        cnt <- append(cnt, exnew, after=idx.0-1)
        write(cnt, file=file)
    }
}
Run Code Online (Sandbox Code Playgroud)

检查包裹

shell(paste("R CMD check", path), intern=FALSE)
Run Code Online (Sandbox Code Playgroud)

构建并安装包

shell(paste("R CMD INSTALL",  path), intern=FALSE)
Run Code Online (Sandbox Code Playgroud)

调查帮助文件

require("mypkg")

foo(x="a", y=letters)
foo(x="a", y=1:10)

?foo
Run Code Online (Sandbox Code Playgroud)

替代方式:分离构建和安装

shell(paste("R CMD INSTALL --build --data-compress=gzip ",  path), intern=FALSE)

install.packages(paste0(pkg.name, "_1.0.zip"), type="win.binary")

require("mypkg")

?foo
Run Code Online (Sandbox Code Playgroud)