+ - 0:00:00
Notes for current slide
Notes for next slide

Good practice for writing R code and R packages

https://jarbel.github.io/Rgoodpractice/rpresentation.html Slides very closely following http://style.tidyverse.org/

Julyan Arbel & Alexis Arnaud

February 8, 2018

1 / 30

1. R coding style

2 / 30

Files

3 / 30

Names

# Good
fit_models.R
utility_functions.R
# Bad
fit models.R
foo.r
stuff.r

Structure

# Load data ---------------------------
# Plot data ---------------------------
4 / 30

Syntax

5 / 30

Object names

Strive for names that are concise and meaningful.

# Good
day_one
day_1
# Bad
first_day_of_the_month
DayOne
dayone
djm1

Avoid using already existing names.

# Bad
T <- FALSE
c <- 10
mean <- function(x) sum(x)
6 / 30

Spacing

Any style guide is fundamentally opinionated...

# Good Hadley
average <- mean((feet / 12) + inches, na.rm = TRUE)
sqrt(x^2 + y^2)
x <- 1:10
base::get
# Good Alexis
average <- mean(
( feet / 12 ) + inches
, na.rm = TRUE
)
sqrt( x^2 + y^2 )
x <- 1:10
base::get
# Bad
average<-mean(feet/12 + inches,na.rm=TRUE)
sqrt(x ^ 2 + y ^ 2)
x <- 1 : 10
base :: get
7 / 30

Indenting

# Good
if (y < 0 && debug) {
message("y is negative")
}
# Bad
if (y < 0 && debug)
message("Y is negative")
8 / 30

Long lines

Strive to limit your code to 80 characters per line.

# Good
do_something_very_complicated(
something = "that",
requires = many,
arguments = "some of which may be long"
)
# Bad
do_something_very_complicated("that", requires, many, arguments,
"some of which may be long"
)
9 / 30

Assignment

# Good
x <- 5
# Bad
x = 5
10 / 30

Automatic styling

You can use Ctrl + Shift + A or Command + Shift + A

Or lintr and styler packages

install.packages(c("lintr", "styler"))
library("lintr")
library("styler")
11 / 30

lintr package

lintr can be used o a source file, eg bad_style.R being the following source:

# Spacing
average<-mean(feet/12 + inches,na.rm=TRUE)
sqrt(x ^ 2 + y ^ 2)
x <- 1 : 10
base :: get
# Indenting
if (y < 0 && debug)
message("Y is negative")
# Assignment
x = 5

Then run

lint("bad_style.R")
12 / 30

lintr package

13 / 30

styler package

14 / 30

styler package

You can use the style_text() function as follows

ugly_code <- "a<-function( x){1+1} "
style_text(ugly_code)
# Bad
a<-function( x){1+1}
# Good
a <- function(x) {
1 + 1
}
15 / 30

styler package

As well as the following variants of style_text():

  • style_file() styles .R and/or .Rmd files.
  • style_dir() styles all .R files in a directory.
  • style_pkg() styles the source files of an R package.
  • RStudio Addins for styling the active file, styling the current package and styling the highlighted code region.
16 / 30

Other tidying packages

Get automatic advice about your package

Install and run goodpractice package for Advice (that) includes functions and syntax to avoid, package structure, code complexity, code formatting, etc.

Remove typos!

Use the devtools::spell_check() function.

17 / 30

2. Create R packages

19 / 30

System settings - Customization of R profile

Create a R profile file .Rprofile with the path to your local library if you use local libraries into your code, e.g :

.libPaths(new="~/R_libs")

See http://gettinggeneticsdone.blogspot.com/2013/06/customize-rprofile.html for more informations.

20 / 30

Package skeleton

Create a directory with the name of your package, e.g. MyPackage, with inside:

  • the sub-directory R for the R source code
  • the file DESCRIPTION for meta-informations on your package.
dir.create(
path = "MyPackage" )
dir.create(
path = paste(
"MyPackage"
, "R"
, sep = .Platform$file.sep ) )
file.create(
path = paste(
"MyPackage"
, "DESCRIPTION"
, sep = .Platform$file.sep ) )
21 / 30

DESCRIPTION file

cat( c(
"Package: MyPackage"
, "Version: 0.1"
, "Date: 2018-02-08"
, "Type: Package"
, "Title: My nice package"
, "Author: A. Arnaud"
, "Maintainer: Alexis Arnaud <alexis.arnaud@inria.fr>"
, "Description: Basic package to display 2 ggplot2 plots."
, "License: GPLv3"
, "URL: https://github.com/jarbel/Rgoodpractice.git" )
, file = paste(
"MyPackage"
, "DESCRIPTION"
, sep = .Platform$file.sep )
, sep = "\n"
, append = TRUE )
22 / 30

R code files

multiplot : http://www.cookbook-r.com/Graphs/Multiple_graphs_on_one_page_(ggplot2)/

cat( c(
"plot_boxplot <- function(data) {
if ( !is.data.frame(x = data) ) data <- as.data.frame(x = data)
data_melt <- melt(data = data)
plot_pairs <- ggpairs(data = data)
plot_boxplot <- ggplot(
data = data_melt
, aes(
x = variable
, y = value
, fill=variable)
) + geom_boxplot( )
multiplot(
plot_pairs
, plot_boxplot
, cols = 2)
}" )
, file = "plot_functions.R"
, sep = "\n"
, append = TRUE )
23 / 30

R code documentation

Use the Roxygen templates to start the documentation:

24 / 30

R code documentation

And fill the Roxygen fields in order to best describe your function:

  • Title of the function
  • @description Some description
  • @param name of each parameter and a short description (type, default value ...)
  • @return value of the function output
  • @author author of the function
  • @seealso link to other functions or packages, e.g. \code{ \link[GGally]{ggpairs} }
  • @keywords some keywords for the code indexation
  • @examples one or several examples on how to use the function
  • @importFrom to import some package or functions during the installation and the loading of the function
  • @export
25 / 30

Documentation generation with roxygen2

Now, you just need to move your R files to the R directory of your package, and then run Roxygen before building and installing your package.

library(package = "roxygen2")
for ( file in c( "plot_functions.R", "multiplot.R" ) ) {
file.copy( from = file
, to = paste(
"MyPackage"
, "R"
, file
, sep = .Platform$file.sep ) ) }
roxygenize(
package.dir = "MyPackage"
, clean = TRUE )
library(package = "tools")
Rcmd(args = "build MyPackage")
## or with a shell : R CMD build MyPackage
install.packages(pkgs = "MyPackage_0.1.tar.gz")
library(package = "MyPackage")
26 / 30

Test

n_col <- 3
n_row <- 1e3
m_test <- t(
x = matrix(
data = rnorm(
n = n_col * n_row
, mean = 0
, sd = 1
)
, nrow = n_col
, ncol = n_row
, dimnames = list(
"Variables" = paste("V ", seq_len(length.out = n_col), sep = "")
, "Observations" = NULL
)
) * c(0.1, 1, 3) + c(-1, 1, 0)
)
plot_boxplot(data = m_test)
27 / 30

Test

28 / 30

1. R coding style

2 / 30
Paused

Help

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