notes for create R package
Notes for Creating an R package
Reference
Basic Structure
pkg (包的名字,请使用一个有意义的名字,不要照抄这里的pkg三个字母)
|
|--DESCRIPTION (描述文件,包括包名、版本号、标题、描述、依赖关系等)
|--R (函数源文件)
|--function1.R
|--function2.R
|--...
|--man (帮助文档)
|--function1.Rd
|--function2.Rd
|--...
|--demo
|--data
|--data1.rda (saved by save())
|--src
|--inst
|--doc
|--*.Rnw (Vignette)
|--...
DESCRIPTION
Package: pkgname
Version: 0.5-1
Date: 2004-01-01
Title: My First Collection of Functions
Authors@R: c(person("Joe", "Developer", role = c("aut", "cre"),
email = "Joe.Developer@some.domain.net"),
person("Pat", "Developer", role = "aut"),
person("A.", "User", role = "ctb",
email = "A.User@whereever.net"))
Author: Joe Developer and Pat Developer, with contributions from A. User
Maintainer: Joe Developer <Joe.Developer@some.domain.net>
Depends: R (>= 1.8.0), nlme
Imports: utils
Suggests: MASS
Description: A short (one paragraph) description of what
the package does and why it may be useful.
License: GPL (>= 2)
URL: http://www.r-project.org, http://www.another.url
BugReports: http://pkgname.bugtracker.url
Keyword: quantile
- The ‘Package’, ‘Version’, ‘License’, ‘Description’, ‘Title’, ‘Author’, and ‘Maintainer’ fields are mandatory.
- Fields ‘Author’ and ‘Maintainer’ can be auto-generated from ‘Authors@R’, and may be omitted if the latter is provided: however if they are not ASCII we recommend that they are provided.
- version: 0.1.9
- Depends和Imports有细微差别:前者将导致加载你的包时,依赖包也被明确加载进来,用户可以直接使用这些包中的函数;后者不会导致那些包被明确加载,只有你的包在调用那些函数,但那些函数对用户是不可见的(除非用户明确加载之)。
Install
cd ~/dev/
R CMD INSTALL myfirstpkg
library(myfirstpkg)
myfun()
Rd file
% File src/library/base/man/load.Rd
\name{load}
\alias{load}
\title{Reload Saved Datasets}
\description{
Reload the datasets written to a file with the function
\code{save}.
}
\usage{
load(file, envir = parent.frame())
}
\arguments{
\item{file}{a connection or a character string giving the
name of the file to load.}
\item{envir}{the environment where the data should be
loaded.}
}
\seealso{
\code{\link{save}}.
}
\examples{
## save all data
save(list = ls(), file= "all.RData")
## restore the saved values to the current environment
load("all.RData")
## restore the saved values to the workspace
load("all.RData", .GlobalEnv)
}
\keyword{file}
can be generated by package.skeleton()
\emph{}
\strong{}
\code{} : for R code
\eqn{} : $$ latex
\deqn{} : displaymath
\kbd{} : keyboard
\pkg{package}
\file{}
\email{}
\cite{}
\itemize{\item[ad] }
\enumerate{\item}
roxygen2 and emacs
##' My fun
##'
##' do something
##'
##' more detail
##'
##' @author Minzhao Liu
##' @source \url{http://www.google.com}
##' @examples
##' x <- 1
They are directly above the R function.
C-c C-o
Use:
library(roxygen2)
roxygenize('myfirstpkg')
After that, can R CMD install myfirstpkg
again and now, we can use
?myfun
To use shared library:
@useDynLib qrmissing
To define method:
##' @rdname QRMissingBi
##' @method summary QRMissingBi
##' @S3method summary QRMissingBi
roxyPackage
#' Hello World function
#'
#' Say Hello
#'
#' This function is a basic Hello World function in R. It uses the
#' \code{\link{paste}} function to say hello to someone.
#'
#' @param name. Default is set to 'World'.
#' @author Markus Gesmann
#' @keywords print
#' @seealso \code{\link{paste}}
#' @export
#' @examples
#' hello()
#' hello(c("Alice", "Bob")
hello <- function(name="World"){
paste("Hello", name)
}
Define DESCRIPTION in data
myDescription <- data.frame(
Package="HelloWorld",
Type="Package",
Title="Hello World",
Author="Markus Gesmann <markus.gesmann@gmail.com>",
Maintainer="Markus Gesmann <markus.gesmann@gmail.com>",
Depends="R (>= 2.10.0)",
Description="Hello World package",
License="GPL (>= 3)"
)
create package with roxy.package
:
library(roxyPackage)
roxy.package(
pck.source.dir="~/Desktop/HelloWorld/",
R.libs="/Library/Frameworks/R.framework/Resources/library/",
repo.root="~/Desktop/repo",
pck.version="0.1",
pck.description=myDescription,
actions=c("roxy", "doc", "html", "package", "check")
ChangeLog=list(
added=c("new extra NULL feature", "new oblivion matrix"),
fixed=c("finally resolved the reandom results bug")
)
)
Just execute above script. Further we only need to update above script for DESCRIPTION infomation.
NAMESPACE
写R包时,有时候可能会遇到某些函数只是为了另外的函数的代码更短而从中抽象、独立出来的,这些小函数仅仅供你自己使用,对用户没什么帮助,他们不需要看见这些函数,这样你就可以在包的根目录下创建一个NAMESPACE文件,里面写上export(函数名)来导出那些需要对用户可见的函数
前面我们也提到DESCRIPTION文件中有Imports一栏,这里设置的包通常是你只需要其部分功能的包,例如我只想在我的包中使用foo包中的bar()函数,那么Imports中就需要填foo,而NAMESPACE中则需要写importFrom(foo, bar),在自己的包的源代码中则可以直接调用bar()函数,R会从NAMESPACE看出这个bar()对象是从哪里来的
roxygen注释对这一类命名空间有一系列标签,如一个函数的文档中若标记了##’ @export,那么这个函数将来就会出现在命名空间文件中(被导出),若写了##’ @importFrom foo bar,那么foo包的bar对象也会被写在命名空间中。这些内容参见R-exts的1.6节和roxygen2的?export帮助
fortran
useDynLib(myfirstpkg)
S3method(plot, mixdir)
S3method(summary, mixdir)
export(gibbs1,
ritcen,
sis1,
sis2)
useDynLib
should follow same name for the package name
If you are using any C or Fortran code in your package, you need to copy the necessary files into the src directory. The package will run R CMD SHLIB on these files to create a shared object file of the same name as your package. To insure that the library is properly loaded, you should modify the file which has been placed in the R directory to include a .First.lib() function, which will be called whenever your library is loaded. A function like this one is usually sufficient:
".First.lib" <-
function(libname,pkgname)
library.dynam("package",pkgname,libname)
where the first argument to library.dynam() is your package name in quotes without any suffix
The useDynLib line declares the connection between the FORTRAN source code and R. Within R, the FORTRAN subroutines are called with .Fortran.
The export line declares, to some extent, the visibility of your R functions to the package user. You should only list functions you want the user to call themselves, not any of the internal functions that implement your algorithms.
Create an R manual page for each of the functions you listed in the export section of NAMESPACE, and also all of the data objects you put in the data directory
Dynamically loading the shared object into a running version of R. This is done with dyn.load() for a non-packaged function, and with library.dynam (via .First.lib()) for a function in a package.
Vignette
in inst/doc/*.Rnw
. Now may support *.Rmd
file (after R 3.0.0)?
src
Publish
R CMD check myfirstpkg
R CMD build myfirstpkg
Notes from Jeff Leak
https://github.com/jtleek/rpackages
R functions
- class:
classname-class.R
,leek-class.R
- method:
newclass-methodname-method.R
,leek-plot-method.R
Vignettes
files should be in packagename/vignettes
, during package building, the
y are moved to packagename/inst/doc
. For HTML, the file should be vignette.Rmd
,
for PDF, vignette.Rnw
Unit Tests
Use testthat
package. File name : test-area-packagename.R
in the
inst/tests
. Then make a run-all.R
in a separate directory called tests
, in
which:
library(testthat)
library(mypackage)
test_package("mypackage")
Then when running R CMD check
, there will be errors if any tests fail. See https://github.com/jtleek/rpackages for examples.