The goal of this talk is to introduce the use of tools that simplify the development of packages in R. It’s a free and summarized interpretation of the course prepared by:
The original materials can be found at https://github.com/hadley/pkg-dev
We are going to make a toy package, following this chapter
All code in these class notes should not be run in the .rmd but in the package environment
install.packages(c(
"devtools", "roxygen2",
"testthat", "covr", "pkgdown"
))
usethis::use_course("http://bit.ly/pkg_dev")
The main tool for creating an R-package is usethis
, a package that contains a set of functions that simplify the work
create_package()
This creates the directory with the basic structure of the package
usethis::create_package('~/Desktop/tstpckg')
Example. We want a function that concatenates factors with properties that are cooler than the default
a <- factor(c("character", "in", "the", "streets"))
b <- factor(c("integer", "in", "the", "sheets"))
c(a,b)
## [1] 1 2 4 3 2 1 4 3
factor(c(as.character(a), as.character(b)))
## [1] character in the streets integer in the
## [8] sheets
## Levels: character in integer sheets streets the
We create the function fbind
fbind <- function(a, b) {
factor(c(as.character(a), as.character(b)))
}
To add it into the package we use usethis::use_r("file-name")
usethis::use_r("fbind")
We write our function in R/fbind.R
With devtools::load_all()
(or ctrl+shift+L) we can load the functions of the package for testing on the console.
We have our function that does what we want. What now?
Check
analyses the package to find possible errors
, warnings
or notes
. These are three levels of severity of the problems presented by the package.
For a package to be accepted in CRAN it must have neither errors nor warnings, and the notes are inspected by the reviewers (in general there is a note for packages that are uploaded for the first time, and there should be no others than this one).
It is important to run many checks throughout the development of the package and keep it clean. It is better to solve the problems as soon as they appear.
devtools::check()
We can also run them from Build --> Check.
What does it return?
This indicates that:
To create the license we can use usethis::use_mit_license(name = 'Your Name')
function
To create the documentation we use the devtools::document()
function or ctrl+shift+D and the roxygen2 package
We stand on the function –> Code –> Insert roxygen skeleton
Once the package works, we can use devtools::install()
to install and use it
It is important to add automatic tests to our package, so that every time we make a change, the tests automatically check that another part of the package has not been broken.
To do this, we use the use_test
function which creates a new script in the tests/testthat folder where we can write our tests
usethis::use_test('fbind')
For example, for ‘fbind’ we could set up the following test
test_that("fbind works", {
factor1 <- factor(c('Hi','there'))
factor2 <- factor(c('we', 'are', 'testing', 'this', 'function'))
expect_equal(fbind(factor1,factor2),
factor(c('Hi','there','we', 'are', 'testing', 'this', 'function')))
})
Here we use the test_that
function to build the test, and inside it, expect_equal
to indicate that the result of the fbind should be such a factor.
In the test script we have the run tests button at the top right. The result is:
This indicates that the test is working properly.
Now every time we do a check, it will also run all the tests.
The test coverage indicate the proportion of the code that is covered by tests. Not all code is easily testable, but a high coverage is a guarantee that there are no hidden problems. (in the original notes there is a detail explanation on how to check coverage)