R tidyverse Cheat Sheet β€” dplyr, ggplot2, tidyr, readr, purrr | Dataplexa

R tidyverse

dplyr  Β·  ggplot2  Β·  tidyr  Β·  readr  Β·  purrr  Β·  pipe  Β·  tidy data  Β·  wrangling  Β·  visualization

Sheet 2 of 2 tidyverse 2.x Intermediate Printable

tidyverse Packages at a Glance

quick reference
PackagePurposeKey functionsUse when…
dplyr Data manipulation filter, select, mutate, group_by, summarise, arrange, joinTransforming data frames row/column-wise
ggplot2Data visualization ggplot, aes, geom_*, facet_*, scale_*, theme_* Building any chart or graph
tidyr Reshaping data pivot_longer, pivot_wider, separate, unite, drop_na Converting wide↔long, fixing messy data
readr Read flat files fast read_csv, read_tsv, read_delim, write_csv Importing CSV / TSV files
purrr Functional programming map, map_dbl, map_df, walk, reduce, keep, discard Replacing loops; working with lists
stringrString manipulation str_detect, str_replace, str_extract, str_split Cleaning and searching text columns
forcatsFactor handling fct_reorder, fct_lump, fct_relevel, fct_infreq Reordering / collapsing factor levels
lubridateDate & time ymd, dmy, hms, year, month, floor_date, interval Parsing and computing with dates
Load the whole tidyverse
library(tidyverse)   # loads dplyr, ggplot2, tidyr, readr, purrr, stringr, forcats, tibble

# Or load individually
library(dplyr)
library(ggplot2)

dplyr β€” Data Manipulation

filter Β· select Β· mutate Β· summarise Β· join
filter() Β· select() Β· arrange()
df |>
  filter(score > 80, pass == TRUE) |>
  select(name, score)              |>
  arrange(desc(score))

# select helpers
select(df, starts_with("sc"))
select(df, contains("name"))
select(df, where(is.numeric))
select(df, -id)        # drop column
mutate() Β· rename() Β· relocate()
df |>
  mutate(
    grade  = if_else(score>=90,"A","B"),
    score2 = score * 1.1    # scale up
  ) |>
  rename(student = name) |>
  relocate(grade, .before = score)

# case_when β€” multi-condition
mutate(df, tier = case_when(
  score >= 90 ~ "A",
  score >= 80 ~ "B",
  .default    = "C"
))
group_by() Β· summarise()
df |>
  group_by(dept) |>
  summarise(
    avg_score = mean(score, na.rm=TRUE),
    count     = n(),
    max_score = max(score)
  )

# count() β€” quick frequency
count(df, dept, sort=TRUE)

# add_count() β€” keep all rows
df |> add_count(dept, name="dept_n")

# ungroup when done!
df |> group_by(dept) |> ungroup()
slice() Β· distinct() Β· pull()
# slice β€” pick rows by position
slice(df, 1:5)          # rows 1-5
slice_max(df, score, n=3) # top 3
slice_min(df, score, n=3) # bottom 3
slice_sample(df, n=10)  # random 10

# distinct β€” remove duplicate rows
distinct(df, dept)
distinct(df, dept, .keep_all=TRUE)

# pull β€” extract column as vector
df |> pull(score)
Joins (like SQL)
# All joins take two data frames + by=
left_join(df1, df2, by="id")
# keep ALL rows from df1

right_join(df1, df2, by="id")
# keep ALL rows from df2

inner_join(df1, df2, by="id")
# keep MATCHING rows only

full_join(df1, df2, by="id")
# keep ALL rows from both

anti_join(df1, df2, by="id")
# rows in df1 NOT in df2

# Different column names
left_join(df1, df2,
          by = c("student_id" = "id"))
Always ungroup()! A grouped data frame carries its grouping silently. Call ungroup() after summarise() or you'll get unexpected results in the next step.

tidyr β€” Reshape Data

pivot Β· separate Β· unite Β· drop_na
pivot_longer() β€” wide β†’ long
# Wide: one col per year
#   name  2022  2023  2024
#   Alice   80    85    90

df |> pivot_longer(
  cols      = starts_with("202"),
  names_to  = "year",
  values_to = "score"
)
# Long: name | year | score
#       Alice  2022    80
pivot_wider() β€” long β†’ wide
df |> pivot_wider(
  names_from  = year,
  values_from = score
)
separate() Β· unite() Β· drop_na()
# Split "2024-Q1" into two cols
df |> separate(period,
              c("year","quarter"),
              sep = "-")

# Glue two cols into one
df |> unite("full_name",
           first, last, sep=" ")

# Drop rows with any NA
drop_na(df)
drop_na(df, score)  # only col score

readr β€” Read & Write Files

CSV Β· TSV Β· col types Β· write
Read Files
df <- read_csv("data.csv")
df <- read_tsv("data.tsv")
df <- read_delim("data.txt", delim="|")

# Specify column types explicitly
df <- read_csv("data.csv",
  col_types = cols(
    id    = col_integer(),
    name  = col_character(),
    score = col_double()
  )
)

# Skip rows / set NA strings
read_csv("data.csv",
  skip    = 2,
  na      = c("", "NA", "N/A", "null")
)
Write Files
write_csv(df, "output.csv")
write_tsv(df, "output.tsv")

# Append to existing file
write_csv(df, "log.csv", append=TRUE)

# Save R object
saveRDS(df, "df.rds")
df <- readRDS("df.rds")
readr vs read.csv: read_csv() is 10Γ— faster, never converts strings to factors, and gives a tibble with better printing. Always prefer it over base R's read.csv().

purrr β€” Functional Programming

map Β· map_dbl Β· map_df Β· walk Β· reduce
map() family
nums <- list(1:3, 4:6, 7:9)

# map β€” always returns a list
map(nums, mean)
# list: 2, 5, 8

# typed variants β€” force output type
map_dbl(nums, mean)   # dbl vector
map_int(nums, length) # int vector
map_chr(nums, class)  # chr vector
map_lgl(nums, is.null)# lgl vector

# anonymous function (lambda)
map_dbl(nums, \(x) sum(x) / length(x))
map2() Β· pmap() Β· walk()
# map2 β€” iterate over two lists
a <- list(1,2,3)
b <- list(10,20,30)
map2_dbl(a, b, \(x,y) x + y)
# 11 22 33

# pmap β€” iterate over a list of lists
params <- list(n=c(1,2), mean=c(0,5))
pmap(params, rnorm)

# walk β€” for side effects (no output)
walk(dfs, \(d) write_csv(d, "out.csv"))
keep Β· discard Β· reduce Β· map_df
# keep / discard β€” filter a list
nums <- list(1,2,3,4,5)
keep(nums, \(x) x %% 2 == 0)   # 2 4
discard(nums, is.null)

# reduce β€” accumulate
reduce(list(1,2,3,4), `+`)    # 10
reduce(list_of_dfs, left_join,
       by="id")  # join many dfs

# map_df β€” list of dfs β†’ one df
map_df(files, read_csv)
# read and stack many CSVs!
map vs sapply: map() always returns a list β€” predictable and safe. Use typed variants like map_dbl() when you want a specific output type. They throw an error if the result doesn't match β€” much better than silent coercion.

ggplot2 β€” Data Visualization

geoms Β· aes Β· facets Β· themes Β· scales
The Grammar of Graphics
# Every ggplot has 3 parts:
# 1. data  2. aes()  3. geom_*()

ggplot(data = df,
       aes  = aes(x = score, y = grade)) +
  geom_point()

# aes() mappings
aes(x, y,
    color  = group,   # color by var
    fill   = group,   # fill by var
    size   = value,   # size by var
    shape  = type,    # shape by var
    alpha  = conf,    # transparency
    label  = name)    # text labels
Common geom_* layers
geom_point()        # scatter plot
geom_line()         # line chart
geom_bar()          # bar chart (counts)
geom_col()          # bar chart (values)
geom_histogram(bins=30)
geom_boxplot()      # box & whisker
geom_violin()       # violin plot
geom_density()      # density curve
geom_smooth(method="lm") # trend line
geom_text(aes(label=name))
geom_hline(yintercept=50)
geom_vline(xintercept=0)
Full Example β€” scatter with trend
ggplot(mpg, aes(displ, hwy,
               color = factor(cyl))) +
  geom_point(alpha = 0.7) +
  geom_smooth(method = "lm",
              se     = FALSE) +
  facet_wrap(~ class) +
  labs(
    title   = "Engine vs Highway MPG",
    x       = "Displacement (L)",
    y       = "Highway MPG",
    color   = "Cylinders"
  ) +
  theme_minimal()
Facets
# One variable β€” wrap into grid
facet_wrap(~ category)
facet_wrap(~ category, ncol=3)
facet_wrap(~ category, scales="free")

# Two variables β€” fixed grid
facet_grid(row_var ~ col_var)
Scales & Themes
# Colour scales
scale_color_manual(values=c("red","blue"))
scale_color_brewer(palette="Set1")
scale_fill_viridis_c()  # continuous
scale_fill_viridis_d()  # discrete

# Axis scales
scale_x_log10()
scale_y_continuous(limits=c(0,100))
scale_x_date(date_labels="%b %Y")

# Built-in themes
theme_minimal()
theme_classic()
theme_bw()
theme_void()

# Custom theme tweaks
theme(
  legend.position = "bottom",
  axis.text.x     = element_text(angle=45)
)
Save a plot
ggsave("plot.png",
       width  = 8,
       height = 5,
       dpi    = 300)

# Save last plot automatically
# Supports .png .pdf .svg .eps
Layers stack with + β€” not |>. ggplot2 uses + to add layers. Common mistake: using pipe |> between geoms will throw an error.

stringr β€” String Manipulation

detect Β· replace Β· extract Β· split
Detect & Search
x <- c("apple", "Banana", "cherry")

str_detect(x, "an")   # F T F
str_starts(x,  "a")   # T F F
str_ends(x,    "e")   # T F F
str_count(x,   "a")   # 1 1 0
str_which(x,   "an")   # 2 (index)
str_subset(x,  "an")   # "Banana"
Transform & Replace
str_to_lower(x)
str_to_upper(x)
str_to_title(x)
str_trim(x)           # strip whitespace
str_squish(x)         # internal spaces too
str_pad(x, 10, "left") # pad to width
str_replace(x, "a", "@")  # first match
str_replace_all(x, "a", "@")
str_remove(x, "e")
str_extract(x, "[aeiou]+")  # regex
str_c(x, "!", sep="")   # concatenate
str_glue("Hi {x}")     # like f-string

lubridate β€” Dates & Times

parse Β· extract Β· arithmetic Β· floor
Parse Dates
library(lubridate)

ymd("2024-05-15")     # year-month-day
dmy("15/05/2024")     # day-month-year
mdy("May 15, 2024")   # US format
ymd_hms("2024-05-15 09:30:00")
Extract & Arithmetic
d <- ymd("2024-05-15")
year(d)      # 2024
month(d)     # 5
day(d)       # 15
wday(d, label=TRUE)  # "Wed"
quarter(d)   # 2

d + days(30)      # add 30 days
d + months(3)    # add 3 months
floor_date(d, "month")  # 2024-05-01
ceiling_date(d, "week")

tidyverse Mastery Checklist

sheet 2 complete
dplyr & tidyrKey point
Filter rows filter(col > val)
Pick columns select(a, b, -c)
Add / compute column mutate(new = ...)
Group aggregate group_by |> summarise
Wide to long pivot_longer()
Join two data frames left_join(df1, df2)
ggplot2Key point
Base plot ggplot(df, aes(x,y))
Add geometry + geom_point()
Split into panels facet_wrap(~ var)
Set labels + labs(title=, x=)
Change theme + theme_minimal()
Save to file ggsave("plot.png")
purrr Β· stringr Β· readrKey point
Map over a list map(lst, fn)
Get a typed result map_dbl / map_chr
Read CSV fast read_csv("file.csv")
Detect pattern str_detect(x, "pat")
Replace in string str_replace_all()
Parse a date ymd("2024-05-15")
You've completed both R Language sheets!  Β·  Next explore: Java Basics Β· Java Collections Β· Java Streams β€” or try the Python series for comparison.