Biostatistical Computing, PHC 6068

R package

Zhiguang Huo (Caleb)

Wednesday Oct 16, 2017

What is R package

Install R packages

# install.packages("mclust")
## try http:// if https:// URLs are not supported
source("https://bioconductor.org/biocLite.R")
biocLite("impute")
install.packages("mclust_5.3.tar",repos=NULL,type="source")
# in R: 
system("R CMD INSTALL mclust")
#command line: R CMD INSTALL mclust
library(devtools)
install_github("cran/mclust")

Why R package

Use R survival package as an example.

Basic structure of an R Package

Play with survival package

library(survival)
help(package = 'survival')
?coxph
browseVignettes("survival")

Structure of R package

Simple way to create an R Package – package.skeleton()

A minimum example

## two functions and two "data sets" :
if(dir.exists("mypkg")){ ## if mypkg folder already exists, delete that folder
  unlink("mypkg", recursive = TRUE)
}
f <- function(x, y) x+y
g <- function(x, y) x-y
d <- data.frame(a = 1, b = 2)
e <- rnorm(1000)

package.skeleton(list = c("f","g","d","e"), name = "mypkg")

Read-and-delete-me

Read “Writing R Extensions” for more information.

DESCRIPTION

The job of the DESCRIPTION file is to store important metadata about your package. Every package must have a DESCRIPTION. In fact, it’s the defining feature of a package.

DESCRIPTION License

DESCRIPTION Version

Formally, an R package version is a sequence of at least two integers separated by either . or -. For example, 1.0 and 0.9.1-10 are valid versions, but 1 or 1.0-devel are not.

Namespace

Namespace

Namespaces make your packages self-contained in two ways: the imports and the exports. The imports defines how a function in one package finds a function in another.

nrow
## function (x) 
## dim(x)[1L]
## <bytecode: 0x7ffc2bbfa5c8>
## <environment: namespace:base>
dim(mtcars)
## [1] 32 11
dim <- function(x) c(1, 1)
dim(mtcars)
## [1] 1 1
nrow(mtcars)
## [1] 32

Man

Wrap up your package

After editing DESCRIPTION and Man, wrap up your package following the following step

system("R CMD check mypkg")
## system: system invokes the OS command specified by command.
## You may need to revise the Rd files.
system("R CMD BUILD mypkg")
system("R CMD INSTALL mypkg")
install.packages("mypkg_1.0.tar.gz",repos=NULL,type="source")
library(mypkg)
help(package="mypkg")

Your turn to create a R package using skeleton

Problem with skeleton

Advanced techniques: devtools

devtools, starting from sketches. (*) means essential

  1. devtools::create() create an new R package*
  2. Copy your R code in inside R folder*
  3. formatR::tidy dir() clean up the code
  4. Add documentation in R code*
  5. devtools::document() generate R documentation*
  6. devtools::use data() prepare external data
  7. devtools::use testthat() prepare test functions
  8. devtools::test() preform test
  9. devtools::use vignette() generate vignettes
  10. devtools::check() check the package
  11. devtools::build() build the package*
  12. devtools::install() install the package*
  13. others

devtools::create() create an new R package (1*)

## set working directory to be Desktop
WD <- '~/Desktop'
setwd(WD)

devtools::create("myPkgDevtool") 
WD2 <- '~/Desktop/myPkgDevtool'

Copy your R code in inside R folder (2*)

### f.R
f <- function(x, y) x + y

### g.R
g <- function(x, y) x - y

formatR::tidy dir() clean up the code (3)

setwd(WD2)
## make the code neat
formatR::tidy_dir("R")

Add documentation in R code, (4*)

##' Add up two numbers (Description)
##'
##' We want to add up two numbers, blalala... (Details)
##' @title add two numbers
##' @param x first number
##' @param y second number
##' @return sum of two numbers
##' @author Caleb
##' @export
##' @examples
##' f(1,2)
f <- function(x, y) x + y
##' Subtract two numbers (Description)
##'
##' We want to Subtract two numbers, blalala... (Details)
##' @title Subtract two numbers
##' @param x first number
##' @param y second number
##' @return x - y
##' @author Caleb
##' @export
##' @examples
##' g(2,1)
g <- function(x, y) x - y

devtools::document() generate R documentation (5*)

devtools::document() 

Change:

devtools::use data() prepare external data (6)

xxxx <- sample(1000)
devtools::use_data(xxxx)

Change:

Internal data: These objects are only available within the package.

yyyy <- sample(1000)
devtools::use_data(yyyy, internal = TRUE)

devtools::use testthat() prepare test functions (7)

devtools::use_testthat()
test_that("test if f function is correct", {
    expect_equal(f(1,1), 2)
  }
)

test_that("test if f function is correct", {
    expect_equal(f(1,4), 2)
  }
)

devtools::test() preform test (8)

devtools::test()

devtools::use_vignette() generate vignettes (9)

browseVignettes()
devtools::use_vignette("myPkgDevtool")
devtools::use_vignette()

devtools::check() check the package (10)

devtools::check()

devtools::build() build the package (11*)

## build the package
devtools::build()

devtools::install() install the package (12*)

devtools::install() ## seems no vignettes
remove.packages("myPkgDevtool")
install.packages("../myPkgDevtool_0.0.0.9000.tar.gz",repos=NULL,type="source") ## with vignettes

others (internal function)

## h is a internal function for f
h <- function(a,b) a * b

others (depend on other packages)

References

Generate R code

knitr::purl("Rpackage.rmd", output = "Rpackage.R ", documentation = 2)