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
| Package | Purpose | Key functions | Use when⦠|
|---|---|---|---|
| dplyr | Data manipulation | filter, select, mutate, group_by, summarise, arrange, join | Transforming data frames row/column-wise |
| ggplot2 | Data 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 |
| stringr | String manipulation | str_detect, str_replace, str_extract, str_split | Cleaning and searching text columns |
| forcats | Factor handling | fct_reorder, fct_lump, fct_relevel, fct_infreq | Reordering / collapsing factor levels |
| lubridate | Date & 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() Β· 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_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
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() 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
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 & 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 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
| dplyr & tidyr | Key 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) |
| ggplot2 | Key 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 Β· readr | Key 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.