library(tufte) #knitr::opts_chunk$set(results = "hide", echo = FALSE)
library(knitr) options(replace.assign = FALSE, width = 50) opts_chunk$set(fig.path = "knitr_figure/graphics-", cache.path = "knitr_cache/graphics-", fig.align = "center", dev = "pdf", fig.width = 5, fig.height = 5, fig.show = "hold", cache = FALSE, par = TRUE) knit_hooks$set(crop = hook_pdfcrop) knit_hooks$set(par = function(before, options, envir) { if (before && options$fig.show != "none") { par(mar = c(3, 3, 2, 1), cex.lab = .95, cex.axis = .9, mgp = c(2, .7, 0), tcl = -.01, las = 1) }}, crop = hook_pdfcrop)
knitr::include_graphics("logo.png")
RStudio projects make it straightforward to switch between analyses. You can create an RStudio project:
\noindent Each project has its own working directory, workspace, history, and source documents. When we create an RStudio package project, this will create a new directory that contains five files.
.RbuildIgnore
: this file contains a list of file names that the R
build process should ignore when constructing your package. For example, the .Rproj
file.DESCRIPTION
: an overview of your package.^[http://goo.gl/AXSft]*.Rproj
: an RStudio project file.NAMESPACE
: a file that contains exported/exposed package functions^[http://goo.gl/I5yGf8].\noindent Your package directory will also contain two directories.
man
: documentation directory: when you use the help
function in R, the help pages returned live in
this directory.R
: R file directory: all R functions exported from your package belong in this directory.File -> New Project -> New Directory -> R package
Call the package pkg
and select the directory you want to store the package
in. Then click
Create Project
Congratulations - you have just created your first package called pkg
Build -> Build and Reload
r
library("pkg")
hello()
NAMESPACE
file. Notice that the function hello
has been exported.hello
function has also been documented
r
help("hello")
The associated documentation file is in the man
directory.Keeping the NAMESPACE
file and documentation up-to-date is a painful
experience. To ameliorate the process, we use the roxygen2
package to
automatically generate the necessary entries. Above function definitions we add
roxygen2
tags. The tags are of the form:
#' @export #' @details #' @aliases
\noindent Notice the tags are just R comments.
r
library("devtools")
library("roxygen2")
If you don't have them installed, then install them in the usual way
r
install.packages(c("devtools", "roxygen2"))
Build -> Configure build tools
then select
Generate documentation with Roxygen
and click OK. Now when we build our package, RStudio will automatically run
r
library("roxygen2")
roxygenise(".")
R/hello.R
add
r
#' @export
just above the hello
function, i.e.
r
#' @export
hello <- function() {
print("Hello, world!")
}
The export
tag above the hello
function indicates that we
want to export^[Export means the users loading this package, can access
this function.] this particular function. man
directory and the NAMESPACE
file^[The reason for deleting these is that we will automatically generate them using roxygen2
- more details below.]. Select^[The keyboard shortcut for this is Ctrl + B
]
Build -> Build and reload
You should now be able to load your package with
r
library("pkg")
\noindent and call the hello
function
r
hello()
NAMESPACE
file. You should see the entry
r
# Generated by roxygen2: do not edit by hand
export(hello)
\newthought{All R} functions that we create in our package are saved in the
R/
directory^[The files can have a .R
or .r
file
extension. Personally, I prefer .R
]. This directory can contain multiple
files.
R/
directory called basic.R
. In this
file add the following code
r
#' @export
add = function(x, y) {
return(x + y)
}
\noindent Build and reload your package^[Remember the keyboard shortcut
Ctrl + B
]. After reloading your package, the following code should
run
r
library("pkg")
add(1, 2)
check_numeric
r
check_numeric = function(x) all(is.numeric(x))
\noindent and save it in the basic.R
file. check_numeric
in the add
function
r
add = function(x, y) {
if (!check_numeric(c(x, y))) stop("Not numeric")
x + y
}
\noindent Rebuild your package and check that the add
function still works. check_numeric
function^[Remember to export a function, the function name should be in the NAMESPACE
file.], so this will raise an error
r
library("pkg")
check_numeric(1)
\noindent but we can access any non-exported function in a package using the
:::
operator
r
pkg:::check_numeric(1)
\noindent We can access^[The benefit of doing this is that we haven't
loaded the package.] any exported function using ::
r
pkg::add(1, 1)
subtract
and export this function. Rebuild your
package and check that this works OK.add
, check_numeric
and subtract
^[The purpose of this is to highlight how easy it is to create packages.].\newpage
Using roxygen2
simplifies documentation^[The first package I wrote
didn't use roxygen2
and it was a very painful experience.]. The premise of
roxygen2
is simple: describe your functions in comments next to their
definitions and roxygen2
will process your source code and comments to
produce Rd
files in the man/
directory. In theory, you should never
directly edit the Rd
files.
\begin{table}[b] \centering \begin{tabular}{@{} ll} \toprule Tag name & Description \ \midrule \texttt{@title} & Short title for documentation page. \ \texttt{@description} & Longer description page. Skip a line for a \ &\qquad new paragraph.\ \texttt{@param} & Function parameter description. \ \texttt{@inheritParams} & Use the parameter definition from another function. \ \texttt{@export} & Add the function to the \texttt{NAMESPACE} file.\ \texttt{@return} & What does the function return, e.g. a data frame. \ \texttt{@examples} & Function examples (will be run when building). \ \texttt{@rdname} & Point multiple functions to the same help file,\ & \qquad e.g. \texttt{?substr}. \ \texttt{@seealso} & Pointers to other documentation pages. \ \texttt{@importFrom} & Import functions from other packages. \ \bottomrule \end{tabular} \caption{Useful \texttt{roxygen2} tags for documenting functions.}\label{T1-1} \end{table}
roxygen2
descriptions to your add function
r
#' @title A function for adding
#'
#' @description A really good adding function.
#' Perhaps the best function ever!
#'
#' A work of pure genius.
#' @param x a number
#' @param y another number
#' @return a number
#' @export
#' @examples
#' add(5, 10)
#' ## Can also use negative numbers
#' add(-5, 10)
add = function(x, y) {
if (!check_numeric(c(x, y))) stop("Not numeric")
x + y
}
add
function,
i.e. ?add
. Run the examples via
r
example(add)
subtract
function.^[Build \& reload.]multiply
and add an associated help page.^[Build \& reload.]times
r
times = function(x, y) multiply(x, y)
\noindent Export the times
function.^[Build \& reload.]@rdname
tag above the times
function to point to the multiply
help page, i.e.
r
#' @rdname multiply
\noindent Build and reload. Look at ?multiply
and ?times
. Now add
@examples
to the times
function. Look at the new times
help page.We often want to use functions from other R packages. When we do this we need to be explicit, i.e. state what we want and from where. The great thing about R packages, is that when we install a package, the dependencies are also automatically installed.
jrAdvPackage
. First, we need the drat
package
r
install.packages("drat")
\noindent Then we add the jr-packages
repo^[Run the .libPaths()
function to see the repository location.]
r
drat::addRepo("jr-packages")
\noindent Then install as usual
r
install.packages("jrAdvPackage")
jrAdvPackage
contains a very useful function called div
that we want to use
r
library("jrAdvPackage")
div(10, 2)
\noindent To use the div
function within our package, we have to import it first
r
#' @importFrom jrAdvPackage div
\noindent and add an entry to the DESCRIPTION
file
Imports: jrAdvPackage
Create a function divide
that uses the div
function.DESCRIPTION
fileThe DESCRIPTION
file contains high level information about your package.
For example, the package name, a brief description, the licence, and your email
address.
\noindent Open the DESCRIPTION
file and update fields with relevant information. An example is given below.
Package: pkg
Type: Package
Title: My First package
Version: 0.1
Date: 2016-11-01
Authors@R: person(given="Colin", family="Gillespie",
email="colin@jumpingrivers.com", role = c("aut", "cre"))
Maintainer: Colin Gillespie <colin@jumpingrivers.com>
Description: This is my very first package. It contains
exceedingly useful functions, such as add and subtract.
Make sure you add a couple of spaces to indent the
Description otherwise you will waste hours of your life
trying to find the bug.
License: GPL-2 | GPL-3
LazyData: TRUE
One of great things about R packages, is that there are a number of package checks that are available. These include
DESCRIPTION
and NAMESPACE
file.Build -> Check Package
Check that you package passes all tests. ^[CTRL + E] Fix any errors,
warnings or notes.add
function
r
#' add("A", "B")
\noindent Build the package. Does the package still build? Check the package.
Does the package pass all tests?\newpage
Packages can also contain example data sets^[Full details are given at http://goo.gl/Y4Srx4]. Data files^[Note that R code should be "self-sufficient" and not make use of extra functionality provided by the package, so that the data file can also be used without having to load the package.] can be one of three types as indicated by their extension.
.R
or .r
).tab
, .txt
, or .csv
)save()
images (.RData
or .rda
).^[I tend to use RData files.
]\noindent Data files live in the data/
directory.
\noindent Each data file should also have an associated help page. The easiest way to
generate a help page is to use roxygen2
and a dummy R function. Typically,
I have a file called data_help_files.R
, which has entries for the each
data set. For example,^[This is entry is taken from the poweRlaw
package.]
## Entry in data_help_files.R ## Name is name of the data set. #' @name moby #' @aliases moby_sample #' @title Moby Dick word count #' @description The frequency of occurrence of unique words #' in the novel Moby Dick by Herman Melville. #' #' The data set moby_sample is 2000 values sampled from the #' moby data set. #' @docType data #' @format A vector #' @source M. E. J. Newman, "Power laws, Pareto distributions #' and Zipf's law." Contemporary Physics 46, 323 (2005). NULL
data/
directory.r
example_data = data.frame(x = runif(10), y = runif(10))
\noindent Now save^[Use the save
function.] the data frame example_data
in the data/
directory
r
save(example_data, file = "data/example_data.RData")
data_help_files.R
in the R/
directory and
document your new data set.A demo is similar to function examples, but is typically longer and shows how to
use multiple functions together. Demos are plain .R
files that live in the
demo/
package directory. The demos are accessed with the demo()
function.
In demo/
directory, there should also be an 00Index
file, that lists
the demos^[There is a planned demoTitle
tag for roxygen2
, but currently this hasn't been implemented.]. For example,^[Note the white space separation in the 00Index
. Use at least four spaces to avoid annoying error messages.]
demo1 My very first demo
demo2 My very second demo
demo/
directory.first.R
and save it in the demo/
directory.
In this file show how you can use some of your newly created function.00Index
file to the demo/
directory.\newpage
If you want to include more extensive examples or even just further documentation, then you should consider creating a vignette:
a vignette is a small illustration placed at the beginning or end of a book or chapter. ^[http://dictionary.reference.com/browse/vignette]
\noindent We can view vignettes from other packages using the vignette
function
vignette(package = "knitr")
\noindent or to view in your web browser
browseVignettes(package = "knitr")
Vignettes are stored in the vignettes/
directory. The simplest vignette
uses R-markdown and is formatted by the knitr
package. To create a package
vignette, we simply place the file in the vignettes/
directory.
^[The output style is html_vignette
. This is more lightweight (in terms
of file size) than the standard html_document
] For
example, suppose we have a file intro.Rmd
that contains the following text:
^[The UTF-8
line specifies the file encoding.]
--- title: "My very first vignette" author: "Colin Gillespie and Robin Lovelace" output: rmarkdown::html_vignette # nolint start vignette: < # nolint end %\VignetteIndexEntry{My very first vignette} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} ---
This is my first package vignette. I can include mathematics, such as $x^2$. R code is also nicely formatted and displayed.
x = runif(10) x
and plots
plot(x)
knitr
as the vignette engine and provide
an entry for the list of vignettes.**first**
becomes first and
\$x\textasciicircum 2\$
becomes $x^2$.vignettes/
directory in your package.File -> New File -> R markdown
and save it in the vignettes/
directory.Suggests: knitr
VignetteBuilder: knitr
to the DESCRIPTION
file^[Notice the knitr
is only a suggested package, since it's not essential.]. This will tell your package to build vignettes using knitr
.Build -> Build Source Package
and then install the package from source
r
install.packages("pkg_1.0.tar.gz", repos=NULL,
type="source")
\noindent Build and install your package. Check that you can access the
vignette.You package typically also has documentation associated with the package name. For example,
library("pkg") ?pkg
\noindent should bring up an overview of your package. Again we use roxygen2
to generate the man page. Go to
http://goo.gl/W2tJrF
\noindent to view the entry for the poweRlaw
package.
pkg-package.R
in the R/
directory.poweRlaw
package as an example, create a man page for your
package^[What do you think the @aliases
tag does?].Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.