| name | tidyverse |
| description | R data manipulation with dplyr, tidyr, readr, purrr, stringr, forcats, lubridate. Verb pipelines, reshaping, joins, string/date ops, parquet via arrow. Includes data.table for performance. Use when execution language is R. Python equivalent: polars. |
| autoload | never |
| metadata | {"audience":"research-coders","domain":"r-library","library-version":"dplyr 1.2.1","skill-last-updated":"2026-05-08","tags":["r","data-manipulation","tidyverse","dplyr","tidyr"]} |
Tidyverse Skill
R data manipulation with the core tidyverse packages: dplyr (verb-based data transformation), tidyr (reshaping and tidying), readr (fast delimited file I/O), purrr (functional iteration over lists and vectors), stringr (consistent string operations), forcats (factor manipulation for categorical data), and lubridate (date-time parsing and arithmetic). Also covers arrow for parquet I/O and data.table as a high-performance alternative for large datasets. Use when the execution language is R and the task involves data wrangling, reshaping, joining, string processing, date handling, or file I/O. Python equivalent: the polars skill.
What is the Tidyverse?
The tidyverse is a collection of R packages that share a common design philosophy for data science:
- Verb-based grammar: Operations read as sentences --
filter(), select(), mutate(), summarize() describe what you want to do
- Pipe-friendly: Every function takes a data frame as its first argument and returns a data frame, enabling
|> pipe chains
- Tidy data: One observation per row, one variable per column -- functions assume this structure
- Consistent API: Shared conventions across packages (tidyselect helpers, data masking,
.data pronoun)
- Readable pipelines: Code reads top-to-bottom like a recipe, making it self-documenting
The tidyverse is not a single package but a curated set of packages that work together. This skill covers the data manipulation subset; for visualization see the ggplot2 skill; for statistical modeling see the r-stats skill.
Version Notes
Versions installed in the DAAF container (R 4.5.3):
| Package | Version | Key Notes |
|---|
| dplyr | 1.2.1 | .by inline grouping, reframe(), pick() |
| tidyr | 1.3.2 | pivot_longer()/pivot_wider() with .value sentinel |
| readr | 2.2.0 | Second-edition parser, read_csv() returns tibble |
| purrr | 1.2.2 | list_c(), list_rbind(), list_cbind() |
| stringr | 1.6.0 | Consistent str_* functions wrapping stringi |
| forcats | 1.0.1 | fct_na_value_to_level(), fct_cross() |
| lubridate | 1.9.5 | ymd() family, interval(), date arithmetic |
| data.table | 1.18.2.1 | DT[i, j, by] syntax, fread()/fwrite() |
| arrow | 23.0.1.2 | read_parquet()/write_parquet(), Arrow-dplyr integration |
dplyr 1.1+ changes to be aware of:
.by argument in mutate(), summarize(), filter(), slice_*() for inline grouping (no group_by() needed)
reframe() replaces summarize() when results have multiple rows per group
pick() replaces across() inside cur_data() contexts
recode_values() for value-matching (simpler than case_when() for direct mappings; supersedes case_match(), which is soft-deprecated as of dplyr 1.2.0)
consecutive_id() for run-length grouping
join_by() for inequality and overlap joins
How to Use This Skill
Reference File Structure
| File | Purpose | When to Read |
|---|
quickstart.md | Core verbs: filter, select, mutate, group_by + summarize, arrange, pipe | Starting an R data pipeline, basic wrangling |
reshaping.md | pivot_longer, pivot_wider, separate, unite, nest/unnest | Converting between wide and long formats |
joins.md | left_join, inner_join, anti_join, semi_join, join keys, validation | Combining data frames |
io.md | Parquet via arrow, CSV via readr, Excel via readxl, remote fetching via httr2/glue, data import patterns | Reading or writing data files, fetching from HTTP APIs |
strings-dates.md | stringr ops (str_detect, str_replace, regex), lubridate (ymd, date arithmetic) | String processing or date handling |
purrr-functional.md | map/map_dfr/map2, walk, list-columns, nested data patterns | Iterating over lists or nested data |
factors.md | forcats: fct_relevel, fct_reorder, fct_lump, factor ordering | Categorical variable manipulation |
window-ranking.md | row_number, lag/lead, cumsum, ntile, rolling operations | Window functions and ranking within groups |
data-table.md | data.table DT[i, j, by] syntax, fread/fwrite, when to prefer over dplyr | Performance-critical operations on large data |
gotchas.md | NSE vs data masking, .data pronoun, across() patterns, group_by footguns | Debugging unexpected behavior |
Reading Order
- New to tidyverse? Start with
quickstart.md then io.md
- Reshaping data? Read
reshaping.md
- Combining datasets? Read
joins.md
- String or date problems? Read
strings-dates.md
- Performance issues with large data? Read
data-table.md
- Something not working? Check
gotchas.md first
Related Skills
| Skill | Relationship |
|---|
polars | Python equivalent -- covers the same data manipulation domain for Python pipelines |
data-scientist | Methodology routing -- determines which analysis to run; tidyverse implements it |
ggplot2 | Visualization -- takes tidy data produced by tidyverse and creates plots |
r-stats | Statistical modeling -- lm/glm, sandwich robust SEs, diagnostics; tidyverse prepares data for modeling |
fixest | Fixed effects regression -- high-dimensional FE, IV, DiD; tidyverse prepares data for fixest |
r-python-translation | Cross-language reference -- maps tidyverse to polars for bilingual annotation |
Quick Decision Trees
"I need to manipulate data"
Data manipulation task?
├─ Select/drop columns → ./references/quickstart.md (select)
├─ Filter rows → ./references/quickstart.md (filter)
├─ Create/modify columns → ./references/quickstart.md (mutate)
├─ Sort rows → ./references/quickstart.md (arrange)
├─ Aggregate by group → ./references/quickstart.md (group_by + summarize)
├─ Reshape wide to long → ./references/reshaping.md (pivot_longer)
├─ Reshape long to wide → ./references/reshaping.md (pivot_wider)
├─ Join two data frames → ./references/joins.md
├─ Window functions (lag, rank) → ./references/window-ranking.md
└─ Large data performance → ./references/data-table.md
"I need to work with specific types"
Type-specific operation?
├─ String matching/replacement → ./references/strings-dates.md (stringr)
├─ Date parsing/arithmetic → ./references/strings-dates.md (lubridate)
├─ Categorical/factor levels → ./references/factors.md (forcats)
└─ Iterate over lists → ./references/purrr-functional.md (purrr)
"I need to read or write data"
Data I/O?
├─ Read/write parquet (preferred) → ./references/io.md (arrow)
├─ Read/write CSV → ./references/io.md (readr)
├─ Read Excel → ./references/io.md (readxl)
├─ Fetch from HTTP API → ./references/io.md (httr2, glue)
└─ High-speed CSV for large files → ./references/data-table.md (fread)
File-First Execution in Research Workflows
In DAAF research pipelines, R transformations follow the file-first execution protocol -- code is written to .R script files and executed via the run_with_capture.sh wrapper, never run interactively.
The pattern:
- Write transformation code to
scripts/stage{N}_{type}/{step}_{task-name}.R
- Execute via Bash:
bash {BASE_DIR}/scripts/run_with_capture.sh {PROJECT_DIR}/scripts/{script_name}.R
run_with_capture.sh detects the .R extension and uses Rscript automatically
- stdout/stderr are appended to the script file as comments
- If a script fails, create a versioned copy (
_a.R, _b.R, etc.) for fixes
Read agent_reference/SCRIPT_EXECUTION_REFERENCE.md for the complete protocol.
R script structure follows DAAF conventions:
library(dplyr)
library(arrow)
PROJECT_DIR <- "/daaf/research/YYYY-MM-DD_Project"
df <- read_parquet(file.path(PROJECT_DIR, "data", "schools_clean.parquet"))
cat("Loaded:", nrow(df), "rows,", ncol(df), "columns\n")
result <- df |>
mutate(poverty_rate = frl_count / enrollment) |>
group_by(state) |>
summarize(
avg_poverty = mean(poverty_rate, na.rm = TRUE),
n_schools n
.groups
arrangedescavg_poverty
stopifnotnrowresult
stopifnotresultavg_poverty resultavg_poverty
cat nrowresult
cat resultavg_poverty
write_parquetresult file.pathPROJECT_DIR
cat
Quick Reference
Essential Setup
library(dplyr)
library(tidyr)
library(readr)
library(stringr)
library(lubridate)
library(arrow)
Core Operations
| Operation | Code | Package |
|---|
| Filter rows | `df | > filter(x > 5)` |
| Select columns | `df | > select(a, b, c)` |
| Create column | `df | > mutate(y = x * 2)` |
| Sort | `df | > arrange(desc(x))` |
| Group + summarize | `df | > group_by(g) |
| Rename | `df | > rename(new = old)` |
| Distinct rows | `df | > distinct(a, b)` |
| Count | `df | > count(group_col)` |
| Left join | `df1 | > left_join(df2, by = "key")` |
| Pivot longer | `df | > pivot_longer(cols, names_to, values_to)` |
| Pivot wider | `df | > pivot_wider(names_from, values_from)` |
| Read parquet | read_parquet("file.parquet") | arrow |
| Write parquet | write_parquet(df, "file.parquet") | arrow |
| Read CSV | read_csv("file.csv") | readr |
| String detect | str_detect(x, "pattern") | stringr |
| Parse date | ymd("2024-01-15") | lubridate |
| Native pipe | `df | > verb1() |
The Pipe Operator
R 4.1+ provides the native pipe |> which passes the left-hand side as the first argument to the right-hand side. Use |> (not the magrittr %>%) for all DAAF pipelines:
result <- df |>
filter(year == 2020) |>
mutate(rate = count / total) |>
group_by(state) |>
summarize(avg_rate = mean(rate)) |>
arrange(desc(avg_rate))
Topic Index
| Topic | Reference File |
|---|
| filter, select, mutate | ./references/quickstart.md |
| arrange, group_by, summarize | ./references/quickstart.md |
| Pipe operator | ./references/quickstart.md |
| slice, distinct, count | ./references/quickstart.md |
| across(), pick() | ./references/quickstart.md |
| case_when, if_else | ./references/quickstart.md |
| pivot_longer | ./references/reshaping.md |
| pivot_wider | ./references/reshaping.md |
| separate, unite | ./references/reshaping.md |
| nest, unnest | ./references/reshaping.md |
| complete, fill | ./references/reshaping.md |
| left_join, inner_join | ./references/joins.md |
| anti_join, semi_join | ./references/joins.md |
| Join keys, by argument | ./references/joins.md |
| Join validation | ./references/joins.md |
| read_parquet, write_parquet | ./references/io.md |
| read_csv, write_csv | ./references/io.md |
| Arrow integration | ./references/io.md |
| httr2, glue remote fetch | ./references/io.md |
| str_detect, str_replace | ./references/strings-dates.md |
| str_extract, regex | ./references/strings-dates.md |
| ymd, date arithmetic | ./references/strings-dates.md |
| Date components | ./references/strings-dates.md |
| map, map_dfr, walk |
Citation
When this library collection is used as a primary analytical tool, include in the report's Software & Tools references:
Wickham, H. et al. (2019). Welcome to the Tidyverse. Journal of Open Source Software, 4(43), 1686. https://doi.org/10.21105/joss.01686
Cite when: Tidyverse packages are the core data processing engine for the analysis.
Do not cite when: Only used for trivial file I/O in a script primarily using another tool.