R Basics Cheat Sheet — Vectors, Factors, Data Frames, Lists | Dataplexa

R Basics

vectors  ·  factors  ·  data frames  ·  lists  ·  control flow  ·  functions  ·  apply family

Sheet 1 of 2 R 4.x Beginner Printable

R Data Types & Structures at a Glance

quick reference
StructureDimensionsHomogeneous?Mutable?Create withUse when…
vector 1D Yes Yesc(1, 2, 3) Single sequence of same-type values
factor 1D Yes Yesfactor(c("a","b")) Categorical/ordinal data
matrix 2D Yes Yesmatrix(1:6, 2, 3) Numeric grid, linear algebra
array nD Yes Yesarray(1:24, c(2,3,4)) Multi-dimensional tables
list 1D No Yeslist(a=1, b="hi") Mixed types, nested structures
data.frame2D No Yesdata.frame(x=1:3, y=c("a","b","c"))Tabular data (like a spreadsheet)
tibble 2D No Yestibble::tibble() Modern data frame (tidyverse)
R is 1-indexed — the first element is at index [1], not [0] like Python or JavaScript. Assignment uses <- (preferred) or =.

Vectors

atomic · 1D · homogeneous
Create & Access
nums <- c(10, 20, 30, 40)
words<- c("r", "is", "great")
bools<- c(TRUE, FALSE, TRUE)
seq1 <- 1:5          # 1 2 3 4 5
seq2 <- seq(1,10,by=2)  # 1 3 5 7 9
rep1 <- rep(0, times=4)  # 0 0 0 0

nums[1]          # 10  (1-indexed!)
nums[2:4]        # 20 30 40
nums[c(1,3)]     # 10 30
nums[-1]         # 20 30 40 (drop 1st)
Vector Operations (vectorized!)
x <- c(1,2,3); y <- c(10,20,30)
x + y            # 11 22 33
x * 2            # 2  4  6  (scalar)
x ^ 2            # 1  4  9
x > 1            # F  T  T  (logical)
sum(x)           # 6
mean(x)          # 2
length(x)        # 3
sort(x, dec=TRUE) # 3 2 1
rev(x)            # 3 2 1
which(x > 1)     # 2 3 (indices)
Vectorization: R operations apply element-wise automatically — no loops needed for basic math. This is R's superpower for data work.

Factors

categorical · levels · ordered
Create & Inspect
sizes <- factor(c("S","M","L","M","S"))
levels(sizes)       # "L" "M" "S" (sorted)
nlevels(sizes)      # 3
table(sizes)        # L=1 M=2 S=2

# Ordered factor (e.g. ratings)
rating <- factor(
  c("low","high","med"),
  levels = c("low","med","high"),
  ordered = TRUE
)
rating[1] < rating[2]   # TRUE
Modify Factors
# Add a new level
levels(sizes) <- c(levels(sizes),"XL")

# Drop unused levels
sizes2 <- droplevels(sizes)

# Convert to integer codes
as.integer(sizes)   # 3 2 1 2 3

# Convert back to character
as.character(sizes)  # "S" "M" "L"...
Use factors for categorical columns in data frames — they save memory and work correctly in models and ggplot2 colour/shape mappings.

Lists

heterogeneous · named · nested
Create & Access
person <- list(
  name   = "Alice",
  age    = 25,
  scores = c(90,85,92),
  active = TRUE
)

# Three access styles
person[["name"]]  # "Alice" — value
person$name      # "Alice" — shortcut
person["name"]   # list w/ 1 element
person[[3]]      # c(90,85,92) — by pos
Modify & Inspect
# Add / update elements
person$email <- "a@b.com"
person[["age"]] <- 26

# Remove an element
person$active <- NULL

# Inspect structure
length(person)    # 4
names(person)     # "name" "age"...
str(person)       # compact overview
is.list(person)   # TRUE
Nested Lists & lapply
# Nested structure
users <- list(
  list(name="Alice", age=25),
  list(name="Bob",   age=30)
)
users[[1]]$name     # "Alice"

# Apply a function over a list
lapply(users, function(u) u$age)
# returns list: [[1]] 25  [[2]] 30
sapply(users, function(u) u$age)
# simplifies to vector: 25 30
[[ ]] vs [ ]: list[["key"]] extracts the value. list["key"] extracts a sub-list. Always use [[]] or $ when you want the actual element.

Data Frames

2D · tabular · named columns
Create & Inspect
df <- data.frame(
  name  = c("Alice","Bob","Carol"),
  score = c(92, 78, 85),
  pass  = c(TRUE,TRUE,TRUE)
)

nrow(df)     # 3 rows
ncol(df)     # 3 cols
dim(df)      # 3 3
names(df)    # column names
str(df)      # structure overview
summary(df)  # stats per column
head(df, 2)  # first 2 rows
Access & Filter
# Access columns
df$name           # "Alice" "Bob"...
df[["score"]]    # 92 78 85
df[, "score"]    # same

# Access rows — df[row, col]
df[1, ]           # first row
df[1, "name"]   # "Alice"

# Filter rows by condition
df[df$score > 80, ]
# Alice (92) and Carol (85)

# subset() convenience
subset(df, score > 80, c(name,score))
Modify & Add Columns
# Add a new column
df$grade <- ifelse(df$score>=90,"A","B")

# Update existing values
df$score[2] <- 80

# Add rows
new_row <- data.frame(name="Dan",
                       score=70, pass=FALSE)
df <- rbind(df, new_row)

# Merge two data frames
merge(df1, df2, by = "id")
stringsAsFactors: In R < 4.0, strings in data frames became factors by default. Since R 4.0+ this is FALSE by default. Add stringsAsFactors = TRUE explicitly if needed.

Control Flow

if · for · while · switch
if / else if / else
x <- 85

if (x >= 90) {
  cat("A\n")
} else if (x >= 80) {
  cat("B\n")   # prints "B"
} else {
  cat("C\n")
}

# Inline ifelse() — vectorized
ifelse(c(80,95,70) >= 80, "pass", "fail")
# "pass" "pass" "fail"
for / while / repeat
# for loop — over a vector
for (i in 1:3) {
  cat(i, "\n")
}

# for loop — over list / vector
for (fruit in c("apple","mango"))
  print(fruit)

# while loop
n <- 1
while (n <= 3) {
  cat(n, "\n")
  n <- n + 1
}

# break and next (like continue)
for (i in 1:5) {
  if (i == 3) next   # skip 3
  if (i == 5) break  # stop at 5
}
Avoid growing objects in loops! Pre-allocate with result <- vector("numeric", n) before looping, then fill by index. Growing with c() inside a loop is very slow in R.

Functions

def · return · scope · ...
Define & Call
# Basic function
greet <- function(name, greeting = "Hello") {
  paste(greeting, name)   # last expr returned
}
greet("Alice")          # "Hello Alice"
greet("Bob", "Hi")     # "Hi Bob"

# Explicit return
divide <- function(a, b) {
  if (b == 0) return(NA)
  a / b
}
... (dots) & Multiple Returns
# Pass-through extra args with ...
my_mean <- function(x, ...) {
  mean(x, ...)
}
my_mean(c(1,NA,3), na.rm=TRUE)  # 2

# Return multiple values via list
stats <- function(x) {
  list(mean=mean(x), sd=sd(x))
}
res <- stats(1:10)
res$mean  # 5.5
res$sd    # 3.02...
Last expression wins: R functions automatically return the last evaluated expression — no return() needed. Use return() only for early exits.

Apply Family — Loop Alternatives

apply · lapply · sapply · tapply · mapply
FunctionInputOutputUse when…Example
apply() matrix/array vector/list Row or column summaries apply(m, 1, sum)
lapply() list/vector list Always returns a list lapply(lst, mean)
sapply() list/vector simplified Simplify to vector/matrix sapply(lst, length)
vapply() list/vector typed vector Safer sapply with type check vapply(lst,mean,numeric(1))
tapply() vector+groups array Group-by summaries tapply(score, group, mean)
mapply() multiple vectorslist/vectorApply over multiple args mapply(rep, 1:3, 3:1)
apply() — matrix rows/cols
m <- matrix(1:9, nrow=3)
#      [,1] [,2] [,3]
# [1,]   1    4    7
# [2,]   2    5    8
# [3,]   3    6    9

apply(m, 1, sum)  # row sums: 12 15 18
apply(m, 2, sum)  # col sums: 6  15 24
sapply() / lapply()
nums <- list(a=1:5, b=6:10)

lapply(nums, mean)
# list: $a 3  $b 8

sapply(nums, mean)
# a b   (named vector)
# 3 8

# with anonymous function
sapply(1:4, function(x) x^2)
# 1 4 9 16
tapply() — group summaries
scores <- c(80,90,70,95,60,88)
groups <- c("A","B","A","B","A","B")

tapply(scores, groups, mean)
#    A    B
# 70.0 91.0

# like GROUP BY in SQL!

Essential Built-in Functions

base R
FunctionWhat it doesExample
print() / cat() Print to console cat("Hi\n")
paste() / paste0()Concatenate strings paste("a","b",sep="-")
nchar() String length nchar("hello") # 5
toupper/tolower() Change string case toupper("hi") # "HI"
grep() / grepl() Pattern match (returns idx / logical)grepl("^A", names)
gsub() / sub() Replace all / first match gsub("a","@","banana")
is.na() / na.omit()Detect / remove NAs na.omit(c(1,NA,3))
unique() Remove duplicates unique(c(1,2,2,3))
table() Frequency count table(c("a","b","a"))
order() / rank() Indices for sorting / ranks x[order(x)]
Sys.time() Current timestamp t0 <- Sys.time()
tryCatch() Error handling tryCatch(log(-1), warning=...)

Operators Quick Reference

arithmetic · logical · special
OpMeaningExample
+ - * /Arithmetic 3 + 2 # 5
^ or ** Exponent 2^8 # 256
%% Modulo 7 %% 3 # 1
%/% Integer divide 7 %/% 3 # 2
%in% Element in set 3 %in% 1:5 # T
%*% Matrix multiplyA %*% B
OpMeaningNote
<- Assign (preferred)Alt+- shortcut in RStudio
== !=Equal / not equal Returns logical vector
& | AND / OR (vectorized)Element-wise
&& ||AND / OR (scalar)Use in if() conditions
! NOT !TRUE → FALSE
|> Native pipe (R 4.1+)x |> mean()
Pipe Operator |> (R 4.1+)
# Without pipe
round(mean(sqrt(c(1,4,9,16))), 2)

# With pipe — reads left to right
c(1,4,9,16) |> sqrt() |> mean() |> round(2)
# same result — much more readable!

R Basics Mastery Checklist

sheet 1 complete
Vectors & FactorsKey point
Create a vector c(1, 2, 3)
Index (1-based!) x[1] x[2:4]
Vectorized math x * 2 x + y
Make a factor factor(vec)
Ordered factor ordered=TRUE
Lists & Data FramesKey point
Access list element lst$name lst[["k"]]
Filter data frame rows df[df$col > 5, ]
Add column to df df$new <- values
Inspect structure str(df) summary(df)
Merge data frames merge(df1, df2, by=)
Functions & ApplyKey point
Define a function function(x) { ... }
Default argument function(x, n=10)
Apply over list sapply(lst, fn)
Group summary tapply(x, grp, mean)
Pipe result forward x |> fn()
Next up → Sheet 2: R tidyverse  ·  dplyr · ggplot2 · tidyr · readr · purrr · filter · mutate · group_by · summarise · pivot