| name | tidyverse-elegant-r |
| description | Write elegant modern tidyverse R for this course repo—always = for assignment (never <-), dplyr 1.1+ (join_by, .by), native pipe, explicit library() per file, vectorized mutate/case_when, httr2 and purrr possibly/safely, rlang data-mask patterns. Use when editing 03_query_ai, 10_data_management, fixer, or refactoring API/data pipelines. |
Tidyverse-elegant R (SYSEN5381 / dsai)
Project rule: .cursor/rules/tidyverse_elegant.mdc. This skill adds links, package map, and patterns.
Canonical links
Package map (load only what you use)
| Package | Use for |
|---|
| dplyr | filter, mutate, summarise, joins, if_else, case_when, .by, join_by |
| tidyr | pivot_, nest/unnest, separate_, replace_na, complete |
| readr | read_csv, write_csv, read_lines, write_lines |
| tibble | tibble, as_tibble, tidy printing |
| purrr | map, walk, list_rbind, possibly, safely |
| stringr | str_*, vectorized strings in mutate |
| forcats | fct_* |
| lubridate | Dates and datetimes |
| ggplot2 | Graphics |
| httr2 | HTTP: request, req_, resp_ |
| jsonlite | JSON with APIs |
| glue | Interpolation (when many pasted strings) |
| reprex | Minimal reproducible examples when debugging |
Avoid library(tidyverse) as a default; attach the rows you need.
Modern dplyr patterns (gist-aligned)
x |>
dplyr::inner_join(y, dplyr::join_by(id == id), multiple = "error", unmatched = "error")
x |>
dplyr::summarise(m = mean(value), .by = c(grp, year))
purrr::map(splits, fit_one) |> purrr::list_rbind()
Vectorized vs scalar if
- Column logic:
dplyr::case_when(), if_else(), coalesce(), tidyr::replace_na(), stringr inside mutate().
- Script flow:
if (file.exists(".env")) readRenviron(".env") is fine once at top.
rlang snippets for function arguments
my_mean = function(data, var) {
data |> dplyr::summarise(m = mean({{ var }}, na.rm = TRUE))
}
my_mean_by_name = function(data, var) {
data |> dplyr::summarise(m = mean(.data[[var]], na.rm = TRUE))
}
httr2 + errors + mapped requests
- Single request: let
req_perform() error, or tailor with req_error().
- Many URLs: wrap a small function in
purrr::possibly() / safely(), or use req_perform_iterative(..., on_error = "return") when appropriate.
- For typed handling of HTTP conditions,
rlang::try_fetch on specific httr2_http_* classes can be clearer than a huge tryCatch.
Performance workflow
- Run profvis on realistic data.
- Only optimize hot paths; use bench::mark() to compare; ensure equal outputs.
- Prefer keeping dplyr in analysis scripts; consider vctrs / lower-level substitutes mainly for package internals or very tight loops (performant-packages).
Relation to tutorial coding_style.mdc
Tutorial rule prefers %>% and heavy commenting. Scoped elegant paths use |>, explicit library(), and vectorized table logic. Assignment is always = (never <-), same as arrows.mdc and the tutorial rule.