internal/skills/content/r-guide/SKILL.md
R language guardrails, patterns, and best practices for AI-assisted development. Use when working with R files (.R, .Rmd, .qmd), DESCRIPTION, or when the user mentions R/RStudio. Provides tidyverse conventions, vectorization patterns, R Markdown guidelines, and testing standards specific to this project's coding standards.
npx skillsauth add ar4mirez/samuel r-guideInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Applies to: R 4.1+, Statistical Computing, Data Analysis, R Packages, Shiny Apps
purrr::map() over explicit for loops; R is optimized for vector operationsrenv for dependency management, set.seed() for stochastic operations, and R Markdown/Quarto for literate programming.GlobalEnv|>, lambda shorthand \(x))renv -- always commit renv.lockDESCRIPTION (Imports:, Suggests:)renv for full reproducibilitystyler::style_pkg() and lintr::lint_package() before every commitsnake_case for functions/variables, PascalCase for R6/S4 classes<- for assignment (not = outside function arguments)library() at top of scripts; never use require()TRUE/FALSE (never T/F -- they can be overwritten)attach() or setwd() -- use here::here() for project-relative pathsx * 2 not for (i in seq_along(x)) x[i] * 2dplyr::mutate() / dplyr::summarise() for column-wise transformationspurrr::map() family for list iteration (map_dbl(), map_chr(), map_dfr())dplyr::across() for applying functions to multiple columnsfor loops for side effects only (writing files, API calls)vapply() over sapply() when base R is required (explicit return type)rlang::abort() / cli::cli_abort() over stop() for structured conditionsstopifnot() or rlang::arg_match() for argument validationtry() -- always tryCatch() or purrr::safely()validate_dataframe <- function(df, required_cols) {
if (!is.data.frame(df)) {
cli::cli_abort("{.arg df} must be a data frame, not {.obj_type_friendly {df}}.")
}
missing_cols <- setdiff(required_cols, names(df))
if (length(missing_cols) > 0) {
cli::cli_abort(
"Missing required column{?s}: {.field {missing_cols}}.",
class = "validation_error"
)
}
invisible(df)
}
set.seed() before stochastic operations; document the seedrenv::snapshot() after adding or updating packageshere::here() for project-relative paths.Rmd) or Quarto (.qmd) for analysis reportssessioninfo::session_info() at the end of reportsmypackage/ myanalysis/
├── R/ # Source files ├── R/ # Reusable functions
│ ├── data-clean.R ├── analysis/ # Rmd/Quarto (numbered)
│ └── utils.R │ ├── 01-exploration.Rmd
├── tests/ │ └── 02-modeling.qmd
│ ├── testthat.R # Runner ├── data/
│ └── testthat/ │ ├── raw/ # Immutable input
│ └── test-data-clean.R │ └── processed/ # Generated output
├── man/ # roxygen2 ├── output/ # Figures, reports
├── vignettes/ ├── tests/testthat/
├── data-raw/ # Data scripts ├── renv.lock
├── DESCRIPTION └── README.md
├── NAMESPACE # roxygen2
├── renv.lock
└── README.md
roxygen2 for all docs; never edit man/ or NAMESPACE by handdata/raw/, process into data/processed/# Prefer native pipe |> (R 4.1+) over magrittr %>%
result <- raw_data |>
dplyr::filter(year >= 2020, !is.na(revenue)) |>
dplyr::mutate(
revenue_m = revenue / 1e6,
growth = (revenue - dplyr::lag(revenue)) / dplyr::lag(revenue)
) |>
dplyr::summarise(
mean_revenue = mean(revenue_m, na.rm = TRUE),
.by = region
)
# Use {{ }} (embrace) for column names passed as arguments
summarise_by <- function(df, group_col, value_col) {
df |>
dplyr::summarise(
mean_val = mean({{ value_col }}, na.rm = TRUE),
n = dplyr::n(),
.by = {{ group_col }}
)
}
# Use .data pronoun for string column references
filter_column <- function(df, col_name, threshold) {
df |> dplyr::filter(.data[[col_name]] > threshold)
}
# Use across() for multiple columns
standardize_numeric <- function(df) {
df |>
dplyr::mutate(dplyr::across(
where(is.numeric),
\(x) (x - mean(x, na.rm = TRUE)) / sd(x, na.rm = TRUE)
))
}
plot_distribution <- function(df, x_col, fill_col = NULL) {
ggplot2::ggplot(df, ggplot2::aes(x = {{ x_col }})) +
ggplot2::geom_histogram(ggplot2::aes(fill = {{ fill_col }}), bins = 30, alpha = 0.7) +
ggplot2::labs(title = "Distribution", x = NULL, y = "Count") +
ggplot2::theme_minimal(base_size = 14)
}
# Type-stable map variants -- read and combine CSV files
results <- purrr::map_dfr(file_paths, \(path) {
readr::read_csv(path, show_col_types = FALSE) |>
dplyr::mutate(source_file = basename(path))
})
# Safe execution -- capture errors without stopping
safe_read <- purrr::safely(readr::read_csv)
reads <- purrr::map(file_paths, safe_read)
successes <- purrr::map(purrr::keep(reads, \(x) is.null(x$error)), "result")
testthat 3rd edition (Config/testthat/edition: 3 in DESCRIPTION)test-*.R (mirror source: data-clean.R -> test-data-clean.R)test_that("filter_active removes inactive users", ...)covr)expect_snapshot()) for complex output (plots, printed tables)test_that() block is self-containedwithr::local_*() for temporary state changes (env vars, options, files)test_that("summarise_by computes correct group means", {
df <- tibble::tibble(
region = c("east", "east", "west", "west"),
revenue = c(100, 200, 300, 400)
)
result <- summarise_by(df, region, revenue)
expect_equal(nrow(result), 2)
expect_equal(result$mean_val[result$region == "east"], 150)
})
test_that("validate_dataframe errors on missing columns", {
df <- tibble::tibble(a = 1, b = 2)
expect_error(validate_dataframe(df, c("a", "c")), class = "validation_error")
})
Rscript -e 'styler::style_pkg()' # Format package code
Rscript -e 'lintr::lint_package()' # Lint package
Rscript -e 'devtools::test()' # Run tests
Rscript -e 'covr::package_coverage()' # Coverage report
Rscript -e 'devtools::check()' # Full R CMD check
Rscript -e 'renv::snapshot()' # Lock dependencies
Rscript -e 'devtools::document()' # Rebuild roxygen2 docs
quarto render analysis/report.qmd # Render Quarto document
For detailed patterns and examples, see:
development
Zig language guardrails, patterns, and best practices for AI-assisted development. Use when working with Zig files (.zig), build.zig, or when the user mentions Zig. Provides comptime patterns, allocator conventions, C interop guidelines, and testing standards specific to this project's coding standards.
tools
WordPress framework guardrails, patterns, and best practices for AI-assisted development. Use when working with WordPress projects, or when the user mentions WordPress. Provides theme development, plugin architecture, REST API, blocks, and security guidelines.
tools
Toolkit for interacting with and testing local web applications using Playwright. Supports verifying frontend functionality, debugging UI behavior, capturing browser screenshots, and viewing browser logs. Use when testing web apps, automating browser interactions, or debugging frontend issues.
tools
Suite of tools for creating elaborate, multi-component web applications using modern frontend technologies (React, Tailwind CSS, shadcn/ui). Use for complex projects requiring state management, routing, or shadcn/ui components - not for simple single-file HTML/JSX pages.