Advanced

Best Practices

Build reproducible, maintainable data science workflows in R with tidy data principles and professional tooling.

The Tidy Data Workflow

A typical data science project follows this pipeline:

  1. Import

    Read data with readr, readxl, or DBI.

  2. Tidy

    Reshape with tidyr so each variable is a column and each observation is a row.

  3. Transform

    Filter, mutate, summarise with dplyr.

  4. Visualize

    Explore patterns with ggplot2.

  5. Model

    Fit models with tidymodels or base R.

  6. Communicate

    Share results with R Markdown or Quarto.

Reproducible Analysis

R
# 1. Always use renv for dependency management
renv::init()
renv::snapshot()

# 2. Use set.seed() for random operations
set.seed(42)

# 3. Never use setwd() - use RStudio projects
# 4. Use relative paths from project root
data <- read_csv("data/raw/sales.csv")

# 5. Use here() for reliable paths
library(here)
data <- read_csv(here("data", "raw", "sales.csv"))

# 6. Document your session info
sessionInfo()

Project Templates

Project Structure
my-analysis/
  my-analysis.Rproj
  R/
    01-import.R
    02-clean.R
    03-analyze.R
    functions/
      helpers.R
  data/
    raw/           # Never modify raw data
    processed/     # Cleaned data
  output/
    figures/
    tables/
    models/
  docs/
    report.Rmd
  renv.lock
  .gitignore

Handling Large Data

R
# data.table - fastest in-memory data manipulation
library(data.table)
dt <- fread("big_file.csv")  # Much faster than read_csv
dt[age > 30, .(mean_salary = mean(salary)), by = dept]

# arrow - for very large datasets (Parquet format)
library(arrow)
df <- read_parquet("data.parquet")
open_dataset("data/") |>
  filter(year == 2024) |>
  collect()  # Only loads filtered data into memory

# DuckDB - SQL engine for large data
library(duckdb)
con <- dbConnect(duckdb())
dbGetQuery(con, "SELECT * FROM 'data.parquet' WHERE year = 2024")

Package Development Basics

R
# Create a package skeleton
usethis::create_package("mypackage")
usethis::use_r("my_function")
usethis::use_test("my_function")
devtools::document()
devtools::check()

Frequently Asked Questions

Use dplyr for readability and when working with moderately sized data (up to a few GB). Use data.table when performance is critical or your data is very large. Both are excellent; the choice is often about team preference.

Use renv for package management, set.seed() for randomness, R Markdown or Quarto for literate programming, RStudio Projects for working directories, and Git for version control. Never use setwd() or absolute paths.

Create a package when you have functions used across multiple projects, when you want to share code with others, or when you want to enforce documentation and testing. The usethis and devtools packages make it easy.

Learn Quarto for new projects. It is the next generation of R Markdown, supports multiple languages (R, Python, Julia), and is actively developed. Existing R Markdown knowledge transfers directly - the syntax is nearly identical.

Ready to Go Deeper?

Live instructor-led courses from our partners. Affiliate disclosure.