Coding style
Effective comments
Using functions
Defensive programming
Folder organisation
R Projects
R Markdown
19 May 2022
Coding style
Effective comments
Using functions
Defensive programming
Folder organisation
R Projects
R Markdown
It’s easier to revisit a project a few months down the line
It’s easier for others to understand what you’ve done
If you are developing code that you want to be used by others; it increases the chances they will actually use it!
The foundation of writing readable code is to choose a logical and readable coding style, and to stick to it.
Firstly, using meaningful file names for your scripts can immediately improve logical consistency of a project.
01-download-data.R 02-run-my-awesome-analysis.R 03-create-nice-plots.R
abc.R script.R
Similarly any objects that you create should have meaningful names so that you can easily understand what they hold (for variables) or what they do (for functions)
GOOD
species_dat landcover_shp landcover_ras calc_sprich()
BAD
data_from_site_one shapefile Raster my_function()
speciesdat
species_dat
speciesDat
SpeciesDat
A line of code that is visible, but not read by the computer
Signified with #
Should be used to comment ‘why’ rather than ‘what’. For example:
GOOD
# List of grid cells is required for a for loop grid_cells = c('SU41', 'SU42', 'SU43') # For each grid cell, calculate the species richness for(grid in grid_cells) { calc_sprich(grid) }
BAD
# Setting x equal to 1 x = 1
Comments can also be used to break the script into sections:
# 1. Setting variables ####################################### ... # 2. Loading data ############################################ ... # 3. Main analysis ###########################################
This can help plan out a long script:
Write out the actions required in your script as plain text in comments - this helps you to consider the control flow
Fill in with actual code
As a bonus, you will have well commented code without having to add it afterwards
A function is a self-contained block of code that performs a single action
R has loads of in-built functions, such as mean
or sd
:
x = c(2, 3, 4) mean(x)
## [1] 3
sd(x)
## [1] 1
species_dat <- import_data(...) species_dat <- format_data(...) species_dat <- filter_data(...) sprich <- calc_sprich(...)
Function to calculate the square of a number:
square_number <- function(base) { square = base*base return(square) }
We can then call it as we would any other function
square_number(5)
## [1] 25
Functions should be defined before they are called. Good practice would be to save in an external script and import at the beginning of the analysis, after loading the R packages.
Ensure code fails fast and with well defined errors
Creates a little more work BUT will save time when debugging code
Amounts to just adding some checks in your code (e.g. print statements to show where code has got to)
square_number("hello")
## Error in base * base: non-numeric argument to binary operator
square_number <- function(base) { if(!is.numeric(base)) stop("Please ensure base is numeric") square = base*base return(square) } square_number("hello")
## Error in square_number("hello"): Please ensure base is numeric
square_number(2.7)
## [1] 7.29
Example folder structure:
Choose something that works for you
Try to keep raw data separate from processed data
Absolute path: the full path to a file
C:/Laura/project/code/functions.R
Relative path: the path relative to the current working directory
Assuming current working directory is C:/Laura/project
the relative path would be code/functions.R
Note: current working directory + relative path = absolute path
In R we can find the current working directory using:
getwd()
## [1] "C:/Users/grahamlz/GIT_PROJECTS/PRESENTATIONS/best_practice"
Relative paths make code more portable
You can move between computers without having to change paths
You can easily share code with colleagues (they are unlikely to have the exact same file paths as you)
Absolute paths can be useful too. For example, if data are stored outside of the project folder
Uses the one project = one folder mentality
Self-contained project with its own workspace and history
Automatically sets up version control
Keep analysis and writing together
Integrates code chunks in R (or bash, python, SQL, etc.) with plain text in markdown format
Underlying data has changed? No worries, rerun the RMarkdown report and all the figures, tables, embedded values will change magically.
Use for reports, manuscripts, supplementary materials
Record computational analysis in the same way as you would wet/dry lab or field notebooks
You don’t have to do all of this! Work out what is most important for you and the kind of work you do
Build up over time