| name | base-r |
| description | Provides base R programming guidance covering data structures, data wrangling, statistical modeling, visualization, and I/O — using only packages included in a standard R installation. Use when the user writes or debugs R scripts, works with vectors, matrices, lists, data frames, or factors, applies the apply family (sapply, lapply, vapply, tapply), fits models with lm/glm/aov/nls, creates base graphics with plot/barplot/hist/boxplot/par, reads or writes CSV/RDS/RData files, or asks about R language semantics such as environments, scoping, and non-standard evaluation. Also use for R statistical functions (t.test, chisq.test, cor, kmeans, prcomp), string operations, date handling, and file system utilities. Do not use for tidyverse workflows (dplyr, tidyr, purrr), ggplot2, data.table, Shiny, R package development, Rcpp, or Python/Julia/Stata tasks. |
Base R Programming Skill
A comprehensive reference for base R programming — covering data structures, control flow, functions, I/O, statistical computing, and plotting.
Quick Reference
Data Structures
x <- c(1, 2, 3)
y <- c("a", "b", "c")
z <- c(TRUE, FALSE, TRUE)
f <- factor(c("low", "med", "high"), levels = c("low", "med", "high"), ordered = TRUE)
m <- matrix(1:6, nrow = 2, ncol = 3)
m[1, ]
m[, 2]
lst <- list(name = "ali", scores = c(90, 85), passed = TRUE)
lst$name
lst[[2]]
df <- data.frame(
id = 1:3,
name = c("a", "b", "c"),
value = c(10.5, 20.3, 30.1),
stringsAsFactors = FALSE
)
df[df$value > 15, ]
df$new_col <- df$value * 2
Subsetting
x[1:3]
x[c(TRUE, FALSE)]
x[x > 5]
x[-1]
df[1:5, ]
df[, c("name", "value")]
df[df$value > 10, "name"]
subset(df, value > 10, select = c(name, value))
idx <- which(df$value == max(df$value))
Control Flow
if (x > 0) {
"positive"
} else if (x == 0) {
"zero"
} else {
"negative"
}
ifelse(x > 0, "pos", "neg")
for (i in seq_along(x)) {
cat(i, x[i], "\n")
}
while (condition) {
if (stop_cond) break
}
switch(type,
"a" = do_a(),
"b" = do_b(),
stop("Unknown type")
)
Functions
my_func <- function(x, y = 1, ...) {
result <- x + y
return(result)
}
sapply(1:5, function(x) x^2)
sapply(1:5, \(x) x^2)
do.call(paste, list("a", "b", sep = "-"))
Apply Family
sapply(lst, length)
lapply(lst, function(x) x[1])
vapply(lst, length, integer(1))
apply(m, 2, sum)
tapply(df$value, df$group, mean)
mapply(function(x, y) x + y, 1:3, 4:6)
aggregate(value ~ group, data = df, FUN = mean)
String Operations
paste("a", "b", sep = "-")
paste0("x", 1:3)
sprintf("%.2f%%", 3.14159)
nchar("hello")
substr("hello", 1, 3)
gsub("old", "new", text)
grep("pattern", x)
grepl("pattern", x)
strsplit("a,b,c", ",")
trimws(" hi ")
tolower("ABC")
Data I/O
df <- read.csv("data.csv", stringsAsFactors = FALSE)
write.csv(df, "output.csv", row.names = FALSE)
df <- read.delim("data.tsv")
df <- read.table("data.txt", header = TRUE, sep = "\t")
saveRDS(obj, "data.rds")
obj <- readRDS("data.rds")
save(df1, df2, file = "data.RData")
load("data.RData")
con <- file("big.csv", "r")
chunk <- readLines(con, n = 100)
close(con)
Base Plotting
plot(x, y, main = "Title", xlab = "X", ylab = "Y",
pch = 19, col = "steelblue", cex = 1.2)
plot(x, y, type = "l", lwd = 2, col = "red")
lines(x, y2, col = "blue", lty = 2)
barplot(table(df$category), main = "Counts",
col = "lightblue", las = 2)
hist(x, breaks = 30, col = "grey80",
main = "Distribution", xlab = "Value")
boxplot(value ~ group, data = df,
col = "lightyellow", main = "By Group")
par(mfrow = c(2, 2))
par(mfrow = c(1, 1))
png("plot.png", width = 800, height = 600)
plot(x, y)
dev.off()
legend("topright", legend = c("A", "B"),
col = c("red", "blue"), lty = 1)
abline(h = 0, lty = 2, col = "grey")
text(x, y, labels = names, pos = 3, cex = 0.8)
Statistics
mean(x); median(x); sd(x); var(x)
quantile(x, probs = c(0.25, 0.5, 0.75))
summary(df)
cor(x, y)
table(df$category)
fit <- lm(y ~ x1 + x2, data = df)
summary(fit)
coef(fit)
predict(fit, newdata = new_df)
confint(fit)
t.test(x, y)
t.test(x, mu = 0)
t.test(before, after, paired = TRUE)
chisq.test(table(df$a, df$b))
fit <- aov(value ~ group, data = df)
summary(fit)
TukeyHSD(fit)
cor.test(x, y, method = "pearson")
Data Manipulation
merged <- merge(df1, df2, by = "id")
merged <- merge(df1, df2, by = "id", all = TRUE)
merged <- merge(df1, df2, by = "id", all.x = TRUE)
wide <- reshape(long, direction = "wide",
idvar = "id", timevar = "time", v.names = "value")
long <- reshape(wide, direction = "long",
varying = list(c("v1", "v2")), v.names = "value")
df[order(df$value), ]
df[order(-df$value), ]
df[order(df$group, -df$value), ]
df[!duplicated(df), ]
df[!duplicated(df$id), ]
rbind(df1, df2)
cbind(df1, df2)
df$log_val <- log(df$value)
df$category <- cut(df$value, breaks = c(0, 10, 20, Inf),
labels = c("low", "med", "high"))
Environment & Debugging
ls()
rm(x)
rm(list = ls())
str(obj)
class(obj)
typeof(obj)
is.na(x)
complete.cases(df)
traceback()
debug(my_func)
browser()
system.time(expr)
Sys.time()
Reference Files
For deeper coverage, read the reference files in references/:
Function Gotchas & Quick Reference (condensed from R 4.5.3 Reference Manual)
Non-obvious behaviors, surprising defaults, and tricky interactions — only what Claude doesn't already know:
- data-wrangling.md — Read when: subsetting returns wrong type, apply on data frame gives unexpected coercion, merge/split/cbind behaves oddly, factor levels persist after filtering, table/duplicated edge cases.
- modeling.md — Read when: formula syntax is confusing (
I(), * vs :, /), aov gives wrong SS type, glm silently fits OLS, nls won't converge, predict returns wrong scale, optim/optimize needs tuning.
- statistics.md — Read when: hypothesis test gives surprising result, need to choose correct p.adjust method, clustering parameters seem wrong, distribution function naming is confusing (
d/p/q/r prefixes).
- visualization.md — Read when: par settings reset unexpectedly, layout/mfrow interaction is confusing, axis labels are clipped, colors don't look right, need specialty plots (contour, persp, mosaic, pairs).
- io-and-text.md — Read when: read.table silently drops data or misparses columns, regex behaves differently than expected, sprintf formatting is tricky, write.table output has unwanted row names.
- dates-and-system.md — Read when: Date/POSIXct conversion gives wrong day, time zones cause off-by-one, difftime units are unexpected, need to find/list/test files programmatically.
- misc-utilities.md — Read when: do.call behaves differently than direct call, need Reduce/Filter/Map, tryCatch handler doesn't fire, all.equal returns string not logical, time series functions need setup.
Tips for Writing Good R Code
- Use
vapply() over sapply() in production code — it enforces return types
- Prefer
seq_along(x) over 1:length(x) — the latter breaks when x is empty
- Use
stringsAsFactors = FALSE in read.csv() / data.frame() (default changed in R 4.0)
- Vectorize operations instead of writing loops when possible
- Use
stop(), warning(), message() for error handling — not print()
<<- assigns to parent environment — use sparingly and intentionally
with(df, expr) avoids repeating df$ everywhere
Sys.setenv() and .Renviron for environment variables