| name | r-data-science |
| description | R-first data science and statistical analysis with SQL as secondary language. Use when the user asks to analyze data in R, write R scripts, create tidyverse pipelines, build statistical models, work with time series (fable/tsibble), run machine learning workflows (tidymodels), query databases from R (DuckDB, dbplyr), build reproducible pipelines (targets), or parallelize computations (crew/mirai). Triggers on R, tidyverse, dplyr, ggplot2, targets, tidymodels, DuckDB, time series forecasting, or statistical modeling requests. |
R Data Science Skill
R-first data science workflows emphasizing tidyverse idioms, functional programming, and reproducible research.
Core Principles
- Tidyverse-first: Prefer tidyverse solutions; use data.table or base R when performance requires
- Pipelines over scripts: Use
|> (native pipe) for clarity; %>% acceptable in existing codebases
- Functional style: Leverage purrr for iteration; avoid explicit loops
- Lazy evaluation: Use DuckDB/dbplyr to push computation to the database
- Reproducibility: Structure projects with targets for pipeline orchestration
Quick Reference
Data Import/Export
df <- read_csv("data.csv", col_types = cols())
df <- arrow::read_parquet("data.parquet")
df <- readxl::read_excel("data.xlsx", sheet = 1)
Data Manipulation (dplyr + tidyr)
result <- df |>
filter(status == "active") |>
mutate(rate = value / total) |>
group_by(category) |>
summarise(
n = n(),
mean_rate = mean(rate, na.rm = TRUE),
.groups = "drop"
) |>
arrange(desc(mean_rate))
wide <- df |> pivot_wider(names_from = year, values_from = value)
long <- df |> pivot_longer(cols = -id, names_to = "year", values_to = "value")
Iteration (purrr)
results <- map(file_list, read_csv)
means <- map_dbl(df_list, \(x) mean(x$value, na.rm = TRUE))
df |> mutate(result = pmap_dbl(list(a, b, c), \(a, b, c) a + b * c))
Database Workflows
DuckDB (Preferred for Local Analytics)
library(duckdb)
library(dplyr)
con <- dbConnect(duckdb())
duckdb_register(con, "my_table", df)
result <- dbGetQuery(con, "SELECT * FROM my_table WHERE value > 100")
tbl(con, "my_table") |>
filter(value > 100) |>
collect()
dbDisconnect(con, shutdown = TRUE)
duckdplyr (Zero-Copy DuckDB Backend)
library(duckdblyr)
df |>
filter(value > 100) |>
summarise(total = sum(value))
dbplyr (Remote Databases)
library(dbplyr)
con <- DBI::dbConnect(RPostgres::Postgres(), ...)
remote_tbl <- tbl(con, "schema.table_name")
query <- remote_tbl |>
filter(date >= "2024-01-01") |>
group_by(region) |>
summarise(revenue = sum(amount))
show_query(query)
local_df <- collect(query)
Detailed References
Load these as needed based on the task:
Project Structure
Standard layout for targets-based projects:
project/
├── _targets.R # Pipeline definition
├── R/
│ ├── functions.R # Reusable functions
│ └── plots.R # Visualization functions
├── data-raw/ # Original data (gitignored if large)
├── data/ # Processed data
├── output/ # Reports, figures
└── renv.lock # Dependency lockfile
Code Style
- Use tidyverse style guide conventions
- Explicit
library() calls at script top; avoid require()
- Prefer named arguments for clarity:
mean(x, na.rm = TRUE) not mean(x, T)
- Document functions with roxygen2 comments when writing packages
- Use
stopifnot() or cli::cli_abort() for assertions