library(palmerpenguins)
library(tidyverse)
RAdelaide 2025
July 8, 2025
IntroVisualisation.R
R
comes with some very powerful plotting capabilities
graphics
ggplot2
changed everythingcars
dataset
speed
(mph)dist
(ft) each car takes to stopboxplot()
can also create simple figures easilyy ~ x
\(\implies\) y
depends on x
pairs()
ggplot2
ggplot2
has become the industry standard for visualisation (Wickham 2016)tidyverse
Taken from https://r.qcbs.ca/workshop03/book-en/grammar-of-graphics-gg-basics.html
Everything is added in layers
tibble
)x
& y
co-ordinatescolour
, fill
, shape
, size
, linetype
alpha
)cars
speed
(mph)distance
each car takes to stopx
vs y
plot using pointsspeed
distance
x
& y
geom_point()
after calling ggplot()
+
after ggplot()
says “But wait! There’s more…”ggplot2
was created neither pipe had been developed yetgeom_point()
after calling ggplot()
+
after ggplot()
says “But wait! There’s more…”stat_smooth()
What visualisations could we produce to inspect penguins
?
se = FALSE
and see what happensggplot()
\(\implies\) all layers will use thiscolour = species
to geom_point()
\(\implies\) ???~
notation to say all facets depend on species
ggplot2
will detect the most appropriate scale
scale_x_continuous()
and scale_y_continuous()
scale_x_log10()
, scale_x_sqrt()
, scale_x_reverse()
y
scale_colour_discrete()
(Meh…)scale_colour_brewer()
, scale_colour_viridis_d()
scale_colour_brewer()
\(\implies\) RColorBrewer::display.brewer.all()
scale_colour_viridis_d()
will give a colourblind-friendly palette
ggthemes
(Wong 2011)
sex
will have missing values## Try setting different point shapes based on the recorded sex
penguins |>
filter(!is.na(sex)) |> # Remove the penguins with unrecorded sex
ggplot(aes(x = bill_depth_mm, y = bill_length_mm, colour = species)) +
geom_point(aes(shape = sex)) + # Now we have a layer-specific aesthetic
stat_smooth(method = "lm", se = FALSE) +
scale_colour_colorblind()
## Try setting different point shapes based on the recorded sex
penguins |>
filter(!is.na(sex)) |> # Remove the penguins with unrecorded sex
ggplot(aes(x = bill_depth_mm, y = bill_length_mm, colour = species)) +
geom_point(aes(shape = sex), size = 3) + # Change the point size
stat_smooth(method = "lm", se = FALSE) +
scale_colour_colorblind()
scale_shape_manual()
scale_colour_manual()
## Try setting different point shapes based on the recorded sex
penguins |>
filter(!is.na(sex)) |> # Remove the penguins with unrecorded sex
ggplot(aes(x = bill_depth_mm, y = bill_length_mm, colour = species)) +
geom_point(aes(shape = sex), size = 3) +
stat_smooth(method = "lm", se = FALSE) +
scale_colour_colorblind() +
scale_shape_manual(values = c(19, 1)) ## Manually choose the point shapes
?pch
and scroll down a little
## Try setting different point shapes based on the recorded sex
penguins |>
filter(!is.na(sex)) |> # Remove the penguins with unrecorded sex
ggplot(aes(x = bill_depth_mm, y = bill_length_mm, colour = species)) +
geom_point(aes(shape = sex), size = 3) +
stat_smooth(method = "lm", se = FALSE) +
scale_colour_colorblind() +
scale_shape_manual(values = c(19, 1)) +
labs(
# Manually add labels
x = "Bill Depth (mm)", y = "Bill Length (mm)",
colour = "Species", shape = "Sex"
)
p
## Save the figure for exploring theme attributes
p <- penguins |>
filter(!is.na(sex)) |> # Remove the penguins with unrecorded sex
ggplot(aes(x = bill_depth_mm, y = bill_length_mm, colour = species)) +
geom_point(aes(shape = sex), size = 3) +
stat_smooth(method = "lm", se = FALSE) +
scale_colour_colorblind() +
scale_shape_manual(values = c(19, 1)) +
labs(
x = "Bill Depth (mm)", y = "Bill Length (mm)",
colour = "Species", shape = "Sex"
)
theme_grey()
theme_bw()
legend.position = "inside"
element_text()
?theme
\(\implies\) 4 main types of ‘element’element_text()
element_line()
element_rect()
element_blank()
# Make the most horrible figure possible
p + theme_bw() +
theme(
## A slightly exaggerated modification of axis titles
axis.title = element_text(colour = "darkred", size = 16, face = "bold"),
## Make axes thick, blue lines. Ewww
axis.line = element_line(colour = "darkblue", linewidth = 2),
## Hide the underlying grid
panel.grid = element_blank(),
## Make the area background a light grey
plot.background = element_rect(fill = "grey70")
)
geom_bar()
& geom_col()
geom_errorbar()
& geom_errorbarh()
geom_boxplot()
& geom_violin()
geom_density()
& geom_histogram()
geom_line()
, geom_segment()
geom_abline()
, geom_hline()
& geom_vline()
geom_raster()
, geom_tile()
& geom_rect()
sex
as the predictorbody_mass_g
may be a response variablecolour
is generally applied to shape outlinesggplot2
will always separate multiple values/categoryfacet_wrap()
facet_grid()
) will allow for unequal-sized facetsgeom_jitter()
will draw points but with noise in either directionalpha
parameter will make the points partially transparenttrim = FALSE
)ggplot2
is a bit uglyfill = "grey70"
and colour = "black"
binwidth
is automatically set \(\implies\) try binwidth = 100
# A tibble: 6 × 4
species sex weight_mn weight_sd
<fct> <fct> <dbl> <dbl>
1 Adelie male 4043. 347.
2 Adelie female 3369. 269.
3 Gentoo female 4680. 282.
4 Gentoo male 5485. 313.
5 Chinstrap female 3527. 285.
6 Chinstrap male 3939. 362.
geom_col()
## Begin creating a bar plot, with separate panels for each species
penguins |>
filter(!is.na(sex)) |>
summarise(
weight_mn = mean(body_mass_g, na.rm = TRUE),
weight_sd = sd(body_mass_g, na.rm = TRUE),
.by = c(species, sex)
) |>
ggplot(aes(sex, weight_mn, fill = sex)) +
geom_col() +
facet_wrap(~species, nrow = 1)
penguins |>
filter(!is.na(sex)) |>
summarise(
weight_mn = mean(body_mass_g, na.rm = TRUE),
weight_sd = sd(body_mass_g, na.rm = TRUE),
.by = c(species, sex)
) |>
ggplot(aes(sex, weight_mn, fill = sex)) +
geom_col() +
## Now add error bars adding/subtracting from the mean 'on the fly'
geom_errorbar(
aes(ymin = weight_mn - weight_sd, ymax = weight_mn + weight_sd),
width = 0.2 # Set the width of tails on the error bars
) +
facet_wrap(~species, nrow = 1) +
## Some extra code to make the plot look great
scale_y_continuous(expand = expansion(c(0, 0.05))) +
scale_fill_brewer(palette = "Set1") +
theme_bw()
geom_text()
will overlay labels exactly on the pointsgeom_text_repel()
will shift labels marginally away from the pointsgeom_label()
and geom_label_repel()
will add borders and fill to labelsExport
in the Plots
paneA fabulous resource: https://r-graphics.org/
stat_ellipse()
to your plot