This page has been intentionally left blank.
Seriously, it doesn’t have to be about sharing your code (although that is an added benefit!). It is about saving yourself time.
— Hilary Parker April 29, 2014
RStudio
available
: Check if the Title of a Package is Available, Appropriate and Interesting
usethis
: Automate Package and Project Setup
devtools
: Tools to Make Developing R Packages Easier
testthat
: Unit Testing for R
covr
: Test Coverage for Packages
pkgdown
: Make Static HTML Documentation for a Package
Unique & googleable
Describes what the package does (for example, knitr is neater than Sweave)
Only contains letters, numbers, and dots
Begins with a letter, and not end with a period
Unique & googleable
Describes what the package does (for example, knitr is neater than Sweave)
Only contains letters, numbers, and dots
Begins with a letter, and not end with a period
available::available()
makes sure that the package name is valid and unique.
available::available()
makes sure that the package name is valid and unique.
available::available("romato", browse = FALSE)
#> ── romato ─────────────────────────────────────────────────────────────────#> Name valid: ✔#> Available on CRAN: ✔ #> Available on Bioconductor: ✔#> Available on GitHub: ✖ #> Bad Words: ✔#> Abbreviations: http://www.abbreviations.com/romato#> Wikipedia: https://en.wikipedia.org/wiki/romato#> Wiktionary: https://en.wiktionary.org/wiki/romato#> Urban Dictionary:#> Not found.#> Sentiment:???
usethis::create_package()
initialises the basic components of a package.
usethis::create_package()
initialises the basic components of a package.
usethis::create_package("~/Rpkg/romato")
#> Changing active project to romato#> ✔ Creating 'R/'#> ✔ Creating 'man/'#> ✔ Writing 'DESCRIPTION'#> ✔ Writing 'NAMESPACE'#> ✔ Writing 'romato.Rproj'#> ✔ Adding '.Rproj.user' to './.gitignore'#> ✔ Adding '^romato\\.Rproj$', '^\\.Rproj\\.user$' to '.Rbuildignore'#> ✔ Opening project in RStudio
R/
: the R code
man/
: the documentation (generated by roxygen2: do not edit by hand)
DESCRIPTION
: the metadata of the package
NAMESPACE
: how the package interacts with R and with other packages (do not edit by hand)
DESCRIPTION
Package: romatoVersion: 0.0.0.9000Title: What the Package Does (One Line, Title Case)Description: What the package does (one paragraph).Authors@R: person("First", "Last", email = "first.last@example.com", role = c("aut", "cre"))License: What license is it under?Encoding: UTF-8LazyData: trueByteCompile: true
DESCRIPTION
Package: romatoVersion: 0.0.0.9000Title: What the Package Does (One Line, Title Case)Description: What the package does (one paragraph).Authors@R: person("First", "Last", email = "first.last@example.com", role = c("aut", "cre"))License: What license is it under?Encoding: UTF-8LazyData: trueByteCompile: true
0.0.0.9000
MIT License use_mit_license()
: free for anyone to do anything with.
GPLv3 use_gpl3_license()
: changes and bundles must also be GPL.
CC0 use_cc0_license()
: dedicated to public domain, best for data packages.
MIT License use_mit_license()
: free for anyone to do anything with.
GPLv3 use_gpl3_license()
: changes and bundles must also be GPL.
CC0 use_cc0_license()
: dedicated to public domain, best for data packages.
usethis::use_mit_license("Earo Wang")
✔ Setting License field in DESCRIPTION to 'MIT + file LICENSE'✔ Writing 'LICENSE.md'✔ Adding '^LICENSE\\.md$' to '.Rbuildignore'✔ Writing 'LICENSE'
more about license: choose a license
We are going to write some Zomato API wrappers.
usethis::use_r("zomato-api")
● Modify 'zomato-api.R'
An API key is needed, which you can sign up here.
Check out the documentation for developers.
library(httr)library(jsonlite)zomato_search <- function(api_key = NULL, query) { # URL to Zomato API url <- modify_url( url = "https://developers.zomato.com" , path = "/api/v2.1/search" ) # request URL resp <- GET( url = url, config = add_headers("user-key" = api_key), query = list(q = query) ) # read the JSON file parsed <- fromJSON( content( resp, as = "text", type = "application/json", encoding = "UTF-8" ), flatten = TRUE ) # return results parsed$restaurants}ur_key <- "your-api-key"zomato_search(ur_key, query = "Brother Budan Baba Melbourne")
In the R/
folder of a package:
🚫 library()
or require()
: dependencies are managed in the NAMESPACE
file.
🚫 source()
🚫 options()
or par()
🚫 setwd()
Click me to download the R scripts for this workshop.
::fun()
usethis::use_package("httr")
#> ✔ Adding 'httr' to Imports field in DESCRIPTION#> ● Refer to functions with `httr::fun()`
usethis::use_package("jsonlite")
#> ✔ Adding 'jsonlite' to Imports field in DESCRIPTION#> ● Refer to functions with `jsonlite::fun()`
::fun()
usethis::use_package("httr")
#> ✔ Adding 'httr' to Imports field in DESCRIPTION#> ● Refer to functions with `httr::fun()`
usethis::use_package("jsonlite")
#> ✔ Adding 'jsonlite' to Imports field in DESCRIPTION#> ● Refer to functions with `jsonlite::fun()`
httr::fun`%>%` <- magrittr::`%>%`
#' @importFrom httr fun#' @import httr#' @importFrom magrittr %>%
In RStudio, Cmd/Ctrl
+ Shift
+ L
loads all the functions into the environment.
devtools::load_all(".")#> Loading romato
usethis::use_roxygen_md()
#> ✔ Setting Roxygen field in DESCRIPTION to 'list(markdown = TRUE)'#> ✔ Setting RoxygenNote field in DESCRIPTION to '6.0.1'#> ● Re-document
Cmd/Ctrl
+ Opt/Alt
+ Shift
+ R
inserts roxygen skeleton#' Title#'#' @param api_key #' @param query #'#' @return#' @export#'#' @exampleszomato_search <- function(api_key = NULL, query) { ...}
Cmd/Ctrl
+ Opt/Alt
+ Shift
+ R
inserts roxygen skeleton#' Title#'#' @param api_key #' @param query #'#' @return#' @export#'#' @exampleszomato_search <- function(api_key = NULL, query) { ...}
Each roxygen comment is preceded by #'
.
@param
: inputs of the function, followed by a description@return
: what the function returns@export
: make the function visible/accessible to users@examples
: examples of how to use the functionTo know the list of parameters: browseVignettes("roxygen2")
.
Cmd/Ctrl
+ Shift
+ D
to generate /man
files (*.Rd
)==> devtools::document(roclets=c('rd', 'collate', 'namespace'))Updating romato documentationLoading romatoWriting NAMESPACEDocumentation completed
?zomato_search
to preview the man page
Cmd/Ctrl
+ Shift
+ B
to build the package==> R CMD INSTALL --no-multiarch --with-keep.source romato installing to library ‘/Library/Frameworks/R.framework/Versions/3.5/Resources/library’ installing *source* package ‘romato’ ...* R* byte-compile and prepare package for lazy loading* help** installing help indices* building package indices* testing if installed package can be loaded DONE (romato)
Cmd/Ctrl
+ Shift
+ E
to perform R CMD checkStatus: OKR CMD check results0 errors | 0 warnings | 0 notesR CMD check succeeded
Catch bugs before they happen, and guarantee the validity of the code.
Catch bugs before they happen, and guarantee the validity of the code.
usethis::use_test("api")
#> ✔ Adding 'testthat' to Suggests field in DESCRIPTION#> ✔ Creating 'tests/testthat/'#> ✔ Writing 'tests/testthat.R'#> ✔ Writing 'tests/testthat/test-api.R'#> ● Modify 'test-api.R'
Catch bugs before they happen, and guarantee the validity of the code.
usethis::use_test("api")
#> ✔ Adding 'testthat' to Suggests field in DESCRIPTION#> ✔ Creating 'tests/testthat/'#> ✔ Writing 'tests/testthat.R'#> ✔ Writing 'tests/testthat/test-api.R'#> ● Modify 'test-api.R'
For example in the test-api.R
context("Zomato API")test_that("invalid input", { expect_error(zomato_search(api_key = NULL), "Please provide an API key.")})
Cmd/Ctrl
+ Shift
+ T
to perform tests
Sometime I self-soothe by writing unit tests.
— Jenny Bryan (@JennyBryan) April 8, 2018
This is how the world should be and … it is.
This is how the world should be and … it is.
This is how … WTF!?! OK, fixed.
This is how the world should be and … it is.
Code coverage is the % of code that is covered by unit tests.
covr::package_coverage()
covr::report()
displays covr results in a standalone report.
usethis::use_readme_rmd()
✔ Writing 'README.Rmd'✔ Adding '^README\\.Rmd$' to '.Rbuildignore'● Modify 'README.Rmd'
usethis::use_readme_rmd()
✔ Writing 'README.Rmd'✔ Adding '^README\\.Rmd$' to '.Rbuildignore'● Modify 'README.Rmd'
A README file should include:
A brief overview of the package
instructions on how to install
A few examples
usethis::use_vignette("intro-romato")
#> ✔ Adding 'knitr' to Suggests field in DESCRIPTION#> ✔ Setting VignetteBuilder field in DESCRIPTION to 'knitr'#> ✔ Adding 'rmarkdown' to Suggests field in DESCRIPTION#> ✔ Creating 'vignettes/'#> ✔ Adding '*.html', '*.R' to 'vignettes/.gitignore'#> ✔ Adding 'inst/doc' to './.gitignore'#> ✔ Creating 'vignettes/intro-romato.Rmd'#> ● Modify 'intro-romato.Rmd'
usethis::use_vignette("intro-romato")
#> ✔ Adding 'knitr' to Suggests field in DESCRIPTION#> ✔ Setting VignetteBuilder field in DESCRIPTION to 'knitr'#> ✔ Adding 'rmarkdown' to Suggests field in DESCRIPTION#> ✔ Creating 'vignettes/'#> ✔ Adding '*.html', '*.R' to 'vignettes/.gitignore'#> ✔ Adding 'inst/doc' to './.gitignore'#> ✔ Creating 'vignettes/intro-romato.Rmd'#> ● Modify 'intro-romato.Rmd'
Rmarkdown + metadata
---title: "Vignette Title"author: "Vignette Author"date: "2018-05-24"output: rmarkdown::html_vignettevignette: > %\VignetteIndexEntry{Vignette Title} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8}---
Build a website for your 📦 in 2 minutes.
cran-comments.md
, a template for your communications with CRAN when submitting a package. usethis::use_cran_comments()
#> ✔ Writing 'cran-comments.md'#> ✔ Adding '^cran-comments\\.md$' to '.Rbuildignore'#> ● Modify 'cran-comments.md'
devtools::release(spelling = "en_GB")
Version control (Git & Github)
Version control (Git & Github)
Continuous integration
Version control (Git & Github)
Continuous integration
Track changes in NEWS
Version control (Git & Github)
Continuous integration
Track changes in NEWS
S3, S4, R6, Reference class
Version control (Git & Github)
Continuous integration
Track changes in NEWS
S3, S4, R6, Reference class
...
Version control (Git & Github)
Continuous integration
Track changes in NEWS
S3, S4, R6, Reference class
...
R packages by Hadley Wickham
Building a package that lasts by Colin Fay at eRum 2018 workshop
Women's coding workshop by Hadley Wickham, Jenny Brian, Di Cook
R packages by Hadley Wickham
Building a package that lasts by Colin Fay at eRum 2018 workshop
Women's coding workshop by Hadley Wickham, Jenny Brian, Di Cook
You can make a package in 20 minutes by Jim Hester
This page has been intentionally left blank.
Keyboard shortcuts
↑, ←, Pg Up, k | Go to previous slide |
↓, →, Pg Dn, Space, j | Go to next slide |
Home | Go to first slide |
End | Go to last slide |
Number + Return | Go to specific slide |
b / m / f | Toggle blackout / mirrored / fullscreen mode |
c | Clone slideshow |
p | Toggle presenter mode |
t | Restart the presentation timer |
?, h | Toggle this help |
Esc | Back to slideshow |