Modern R Operations

SkillAI & models

Modern R for data analysis and statistics — tidyverse-first (dplyr, tidyr, ggplot2, native |> pipe), with base R and data.table as alternatives. Triggers on: R, Rstats, tidyverse, dplyr, tidyr, ggplot2, pivot/join/group, data.table, purrr map, broom, renv, Quarto.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the Modern R Operations skill

What this skill tells your AI

The instructions your AI receives, as published by 0xdarkmatter/claude-mods in skills/r-ops/SKILL.md and read by ahel’s review.

A tidyverse-first, current-best-practice reference for working in R (2024+): data analysis, statistics, visualization, and reproducible workflow. Opinionated where the community has converged, with base R and data.table flagged as the right tool when they are.

The modern R stack at a glance

JobReach forNot (anymore)
Pipenative |> (R 4.1+)%>% only when you need its placeholder/. features
Data frametibbledata.frame defaults (but it's fine)
Wrangledplyr + tidyrhand-rolled [, subset, aggregate
Read CSVreadr::read_csv (prod), data.table::fread (speed)read.csv
Excel / Parquet / DBreadxl / arrow / DBI+dbplyr
Strings / dates / factorsstringr / lubridate / forcatsbase grepl/POSIXlt/factor juggling
Plotggplot2base graphics (fine for throwaway plots)
Iteratepurrr::map_* + across()sapply (type-unstable); lapply ok in package code
Big / fastdata.table (or dtplyr, arrow+duckdb)
Modelbase lm/glm + broom; tidymodels for CV/tuningcaret
Time seriestsibble + fableforecast::auto.arima (maintenance-only)
ReportsQuarto (.qmd)R Markdown (still works)
Reproducibilityrenv + Projects + here()setwd(), saving .RData

The analysis workflow (and where each reference lives)

import → tidy → transform → visualize → model → communicate
  1. Import — get data in: import-io.md
  2. Tidy & transform — the dplyr/tidyr core: tidyverse-core.md
  3. Clean types — strings, dates, factors: strings-dates-factors.md
  4. Iterate — map over many things, list-columns: iteration-functional.md
  5. Visualize — ggplot2 + EDA: visualization.md
  6. Model — tests, lm/glm, broom, tidymodels: modeling-stats.md
  7. Scale up — when dplyr is too slow: data-table.md
  8. Time series — tsibble/fable, xts: time-series.md
  9. Ship it — projects, renv, Quarto, testing: workflow-tooling.md

Open the reference for the task at hand — they load on demand. For broad orientation, this file is enough.

Core idioms (internalize these)

library(tidyverse)

# The native pipe threads a value into the first argument.
diamonds |>
  filter(carat > 0.5) |>
  mutate(price_per_carat = price / carat) |>
  summarise(
    mean_ppc = mean(price_per_carat),
    n = n(),
    .by = cut                      # per-operation grouping (dplyr 1.1+)
  ) |>
  arrange(desc(mean_ppc))

# across() applies one op to many columns
df |> summarise(across(where(is.numeric), \(x) mean(x, na.rm = TRUE)))

# map over a list/vector, type-stable; combine results
files |> map(read_csv) |> list_rbind(names_to = "source")

# ggplot: data + aesthetic mapping + layered geoms
ggplot(df, aes(x = displ, y = hwy, colour = class)) +
  geom_point() +
  geom_smooth(method = "lm")

Decision shortcuts

Grouping: prefer per-operation .by = over group_by() |> ... |> ungroup() — it avoids sticky-group bugs.

Joins: always write join_by(...) explicitly. Natural joins on shared names are almost always wrong on real data.

Which CSV reader? read_csv (readable, good defaults, production) · fread (fastest, big files) · vroom (many files, column subset).

dplyr or data.table? dplyr for readability and teams; data.table (or dtplyr) when profiling says dplyr is the bottleneck or data is large. arrow+duckdb for larger-than-memory.

lm or tidymodels? Base lm/glm is the right default — reach for tidymodels only when you need cross-validation, tuning, or uniform multi-model comparison.

base R or tidyverse? Tidyverse for analysis, readability, teams. Base R (or data.table) for package development, minimal-dependency scripts, and performance-critical inner loops. The |> pipe is base and dependency-free — use it everywhere.

High-value gotchas

These bite people repeatedly — full detail in the referenced files:

  • stringsAsFactors is FALSE since R 4.0 (2020). Old advice warning about automatic factor conversion on import is stale and sometimes backwards. (import-io)
  • predict(glm_model, type = "response") for probabilities — the default returns link-scale (log-odds). (modeling-stats)
  • cor.test(), not cor() when you care whether a correlation is real. (modeling-stats)
  • sapply is type-unstable — never in function bodies; use a typed map_*. (iteration-functional)
  • map_dfr/map_dfc are supersededmap() |> list_rbind() / list_cbind(). (iteration-functional)
  • ggplot mapping vs setting: aes(colour = class) maps a variable; colour = "blue" sets a constant. Putting a constant inside aes() is the #1 ggplot mistake. (visualization)
  • coord_cartesian(ylim=) zooms; scale_y_continuous(limits=) drops data — the latter silently corrupts smooths/boxplots. (visualization)
  • Factor order is not cosmetic — it sets ggplot axis/legend order and regression reference levels. fct_reorder for plots, fct_relevel for models. (strings-dates-factors)
  • lubridate periods vs durations: months(1) (calendar) vs dmonths(1) (fixed seconds); use %m+% for safe month-end arithmetic. (strings-dates-factors)
  • data.table := mutates in placeDT2 <- DT is not a copy; use copy(DT). (data-table)
  • xts lag(k = +1) leads (future data); use k = -1. rollapply defaults to center alignment — set align = "right" to avoid look-ahead bias. (time-series)
  • Never setwd() with an absolute path — use an RStudio Project + here::here(). Don't save/restore .RData. (workflow-tooling)

Currency note

Reflects the R ecosystem as of 2024–2026: R ≥ 4.3, tidyverse 2.0, native |>, dplyr .by=, the \(x) lambda, list_rbind/list_cbind, the tidyverts (tsibble/fable) time-series stack, and Quarto. Where a once-standard approach has been superseded (base apply → purrr, forecast → fable, R Markdown → Quarto, map_dfrlist_rbind), the modern form leads and the older one is noted for when you encounter it in the wild.

This currency is verified, not assertedscripts/check-r-facts.py guards it against silent drift:

# Structural (PR CI, no network): every CRAN package in the catalog is still
# named in this skill's prose, and the currency note still carries a year.
python scripts/check-r-facts.py --offline        # exit 0 consistent, 10 drift

# Live (weekly freshness job, never blocks a PR): every recommended package
# still resolves on CRAN.
python scripts/check-r-facts.py --live            # exit 10 a package is gone, 7 CRAN unreachable

The canonical package list lives in assets/r-packages.json; when you add or drop a recommendation, update it to match or --offline fails CI.

Signals

GitHub stars
36
Forks
5
Last commit
Aug 2026
Advanced
Catalog kind
skill
Gateway key
r-ops
Source
github.com/0xdarkmatter/claude-mods