Best Practices & Style
48.1 Style (tidyverse style guide)
snake_case names; verbs for functions (clean_data()), nouns for objects.
<- for assignment; spaces around operators and after commas; 2-space indentation; lines ≤ 80 characters.
Use TRUE/FALSE, never T/F.
One pipe step per line.
Automate: styler (styler::style_file()), lintr (lintr::lint_dir()), air (fast R formatter).
48.2 Writing good R code
Write functions for anything you do more than twice; keep them small and pure.
Vectorize; avoid growing objects in loops.
Be explicit about missing values (na.rm, is.na).
Validate inputs (stopifnot, rlang::arg_match, checkmate).
Prefer seq_along()/seq_len() over 1:length(x) (breaks for length 0).
Use vapply/map_* for type stability; avoid sapply in package code.
Use [[ for single elements of lists; drop = FALSE in matrix/data-frame subsetting inside functions.
Avoid attach(), setwd(), rm(list = ls()) in scripts.
Use :: in packages and production scripts.
Set seeds and record sessionInfo()/renv.lock.
Comment *why*, not *what*.
Write tests (testthat) for important functions, even outside packages.
48.3 Common pitfalls
1:length(x) when x is empty floating-point == all.equal(), dplyr::near() any(), all(), or ifelse() growing vectors in loops pre-allocate or map() T/F overwritten always write TRUE/FALSE partial matching with $ on lists/data frames use [[ or tibbles check lengths; tidyverse functions error on bad recycling
sapply returning list or matrix unexpectedly vapply / map_dbl stringsAsFactors surprises (R < 4.0) upgrade or set explicitly hard-coded absolute paths Projects + here()