This is the best book to learn how to build R packages and it is free!
if(!require("xfun")) install.packages("xfun")
xfun::pkg_attach2(c("devtools", "usethis", "roxygen2", "testthat"))
A good package name should be relatively short, easy to pronounce,
informative, and googlable (don’t use common word; but can change the
word, e.g., knitr
, rr2
)
To check the availability of names, we can use the
available
package.
available::available("name_here")
Two ways to do this: use usethis::create_package()
or
create by hand with RStudio.
usethis::create_package("path/to/your/pkg")
RStudio –> New project –> New directory –> R package –> … (git repository?!) –> Create project
We have basic R package structure now!
.Rbuildignore
lists files that we need to have around
but that should not be included when building the R package from
sourceDESCRIPTION
provides meta data of the package; we need
to edit itNAMESPACE
declares the functions that will be exported
and available to use after library()
R/
folder contains all the functions/codeman/
folder contains documentations of functionsLater, we may have folder such as data/
,
tests/
, etc.
Let’s just use the function (get_binomial_name()
) we
wrote.
#' To extract binomial scientific names
#'
#' Some description about the function.
#'
#' @param v Input vector, must be a character vector.
#' @param patterns The Regex pattern to match, default will extract the first two words.
#' @param repl The values to replace the pattern matched that was specified by `patterns`.
#' @param ... Additional arguments to be passed to `[sub]` function.
#' @return A character vector, with the binomial scientific names
#' @examples get_binomial_name(c("Carex aquatilis Wahlenb.", "Boerhavia coulteri (Hook. f.) S. Watson"))
#'
get_binomial_name <- function(v,
patterns = "^([^ ]+ [^ ]*) .*",
repl = "\\1",
...
){
if(!is.character(v)){ # in case non-character input
stop("The input vector is not character.")
}
v2 = sub(pattern = patterns, replacement = repl, x = v, ...)
return(v2)
}
Copy and paste it into the existing R/hello.R
or create
a new R script file and paste there.
usethis::use_r("get_name")
To try the functions, use devtools::load_all()
or click
“Build –> load all”, which simulates the process of building,
installing, and attaching the package.
To generate the documentations for functions, we can use
devtools::document()
. When running the code for the first
time, if we see the warning below, simply just delete the
NAMESPACE
file and run devtools::document()
again.
Warning: The existing ‘NAMESPACE’ file was not generated by roxygen2, and will not be overwritten.
Or if you prefer to click, “Build –> configure build tools –> check ‘Generate documentation with Roxygen’ –> OK”. Then click “Build –> Document” to generate the documentations.
NOTE: we need to add the following line if we want
to actually export a function (so users can use it with
library()
).
#' @export
Now if we type ?get_binomial_name
in R console, we
should be able to read the documentation!!
DESCRIPTION
You should add enough meta data here to tell more about your package.
If your function uses functions from other package(s), we need to
declare that in the DESCRIPTION
file:
usethis::use_package("stringr", type = "Imports")
# change types "Imports", "Depends", "Suggests", etc.
Then, use the format pkg::function()
in your code.
Read licensing a repository and links within it to learn more about how to choose a license.
Once decided, we can add it with the following examplary code in R:
usethis::use_agpl3_license()
usethis::use_mit_license() # or
You can read the generated LICENSE.md
to have some idea
about what it is.
We should test every function we put in the package.
usethis::use_test()
In the new tests/testthat
folder, we can create R files
to write unit tests. We won’t talk more about it here. To learn more,
read the chapter 12 (testing) in the R packages book; or just look at
the documentation of the testthat
package.
context("Testing names")
test_that("Error returned when working with non-character input", {
expect_error(get_binomial_name(1:5))
})
test_that("It should work with character input", {
expect_equal(get_binomial_name(c("Carex aquatilis Wahlenb.", "Boerhavia coulteri (Hook. f.) S. Watson")),
c("Carex aquatilis", "Boerhavia coulteri"))
})
Once having unit tests written, we can use
devtools::test()
or click “Build –> Test package” to
test whether our function pass tests.
We can use devtools::check()
or click “Build –> Check
package”. Hopefully no errors!
We can try it with devtools::load_all()
when we are
developing it. Once done, we can click “Build –> Clean and Rebuild”
to build and install it on our local computer. Once done, we can use the
package in other projects!