---
title: "Lec 09 - Visualization<br/>with ggplot2"
subtitle: "Lecture 09"
author: "Dr. Colin Rundel"
footer: "Sta 323 - Spring 2025"
format:
  live-revealjs:
    theme: slides.scss
    transition: fade
    slide-number: true
    self-contained: true
execute:
  echo: true
  warning: true
engine: knitr
---

```{r setup}
#| message: False
#| warning: False
#| include: False
options(
  width=80
)

knitr::opts_chunk$set(
  fig.align = "center", fig.retina = 2, dpi = 150,
  out.width = "100%"
)

library(tidyverse)
library(palmerpenguins)
library(bslib)
```

#

![](imgs/hex-ggplot2.png){fig-align="center" width="40%"}


## The Grammar of Graphics

- Visualization concept created by Leland Wilkinson (The Grammar of Graphics, 1999)
- attempt to taxonomize the basic elements of statistical graphics


- Adapted for R by Hadley Wickham (2009)
  - consistent and compact syntax to describe statistical graphics
  
  - highly modular as it breaks up graphs into semantic components 
  
  - ggplot2 is not meant as a guide to which graph to use and how to best convey your data (more on that later), but it does have some strong opinions.


## Terminology

A statistical graphic is a...

- mapping of **data**

- which may be **statistically transformed** (summarized, log-transformed, etc.)

- to **aesthetic attributes** (color, size, xy-position, etc.)

- using **geometric objects** (points, lines, bars, etc.)

- and mapped onto a specific **facet** and **coordinate system**


## Anatomy of a ggplot call

::: {.xsmall}
```r
ggplot(
  data = [dataframe], 
  mapping = aes(
    x = [var x], y = [var y], 
    color = [var color], 
    shape = [var shape],
    ...
  )
) +
  geom_[some geom](
    mapping = aes(
      color = [var geom color],
      ...
    )
  ) +
  ... # other geometries
  scale_[some axis]_[some scale]() +
  facet_[some facet]([formula]) +
  ... # other options
```
:::

## Data - Palmer Penguins

Measurements for penguin species, island in Palmer Archipelago, size (flipper length, body mass, bill dimensions), and sex.

:::: {.columns}
::: {.column width='33%'}
![](imgs/penguins.png){fig-align="center" width="100%"}
:::
::: {.column width='66%' .small}
```{r}
#| echo: False
options(width = 60)
```

```{r}
library(palmerpenguins)
penguins
```

```{r}
#| echo: False
options(width = 65)
```
:::
::::




# Text <-> Plot

##

::: {.xsmall}
> *Start with the `penguins` data frame*


```{r penguins-0}
#| code-line-numbers: "1"
#| output-location: column
#| warning: false
ggplot(data = penguins)
```
:::


##

::: {.xsmall}
> Start with the `penguins` data frame,
> *map bill depth to the x-axis*


```{r penguins-1}
#| code-line-numbers: "4"
#| output-location: column
#| warning: false
ggplot(
  data = penguins,
  mapping = aes(
    x = bill_depth_mm
  )
) 
```
:::


##

::: {.xsmall}
> Start with the `penguins` data frame,
> map bill depth to the x-axis
> *and map bill length to the y-axis.*


```{r penguins-2}
#| code-line-numbers: "5"
#| output-location: column
#| warning: false
ggplot(
  data = penguins,
  mapping = aes(
    x = bill_depth_mm,
    y = bill_length_mm
  )
)
```
:::


##

::: {.xsmall}
> Start with the `penguins` data frame,
> map bill depth to the x-axis
> and map bill length to the y-axis. 
> *Represent each observation with a point*


```{r penguins-3}
#| code-line-numbers: "8"
#| output-location: column
#| warning: false
ggplot(
  data = penguins,
  mapping = aes(
    x = bill_depth_mm,
    y = bill_length_mm
  )
) + 
  geom_point()
```
:::


##

::: {.xsmall}
> Start with the `penguins` data frame,
> map bill depth to the x-axis
> and map bill length to the y-axis. 
> Represent each observation with a point
> *and map species to the color of each point.*

```{r penguins-4}
#| code-line-numbers: "9"
#| output-location: column
#| warning: false
ggplot(
  data = penguins,
  mapping = aes(
    x = bill_depth_mm,
    y = bill_length_mm
  )
) + 
  geom_point(
    mapping = aes(color = species)
  )
```
:::



##

::: {.xsmall}
> Start with the `penguins` data frame,
> map bill depth to the x-axis
> and map bill length to the y-axis. 
> Represent each observation with a point
> and map species to the color of each point.
> *Title the plot "Bill depth and length"*


```{r penguins-5}
#| code-line-numbers: "11"
#| output-location: column
#| warning: false
ggplot(
  data = penguins,
  mapping = aes(
    x = bill_depth_mm,
    y = bill_length_mm
  )
) +
  geom_point(
    mapping = aes(color = species)
  ) +
  labs(title = "Bill depth and length")
```
:::


##

::: {.xsmall}
> Start with the `penguins` data frame,
> map bill depth to the x-axis
> and map bill length to the y-axis. 
> Represent each observation with a point
> and map species to the color of each point.
> Title the plot "Bill depth and length", 
> *add the subtitle "Dimensions for Adelie, Chinstrap, and Gentoo Penguins"*

```{r penguins-6}
#| code-line-numbers: "13-15"
#| output-location: column
#| warning: false
ggplot(
  data = penguins,
  mapping = aes(
    x = bill_depth_mm,
    y = bill_length_mm
  )
) +
  geom_point(
    mapping = aes(color = species)
  ) +
  labs(
    title = "Bill depth and length",
    subtitle = paste("Dimensions for Adelie,",
                     "Chinstrap, and Gentoo",
                     "Penguins")
  ) 
```
:::


##

::: {.xsmall}
> Start with the `penguins` data frame,
> map bill depth to the x-axis
> and map bill length to the y-axis. 
> Represent each observation with a point
> and map species to the color of each point.
> Title the plot "Bill depth and length", 
> add the subtitle "Dimensions for Adelie, Chinstrap, and Gentoo Penguins", 
> *label the x and y axes as "Bill depth (mm)" and "Bill length (mm)", respectively*

```{r penguins-7}
#| code-line-numbers: "16-17"
#| output-location: column
#| warning: false
ggplot(
  data = penguins,
  mapping = aes(
    x = bill_depth_mm,
    y = bill_length_mm
  )
) +
  geom_point(
    mapping = aes(color = species)
  ) +
  labs(
    title = "Bill depth and length",
    subtitle = paste("Dimensions for Adelie,",
                     "Chinstrap, and Gentoo",
                     "Penguins"),
    x = "Bill depth (mm)",
    y = "Bill length (mm)"
  )
```
:::


##

::: {.xsmall}
> Start with the `penguins` data frame,
> map bill depth to the x-axis
> and map bill length to the y-axis. 
> Represent each observation with a point
> and map species to the color of each point.
> Title the plot "Bill depth and length", 
> add the subtitle "Dimensions for Adelie, Chinstrap, and Gentoo Penguins", 
> label the x and y axes as "Bill depth (mm)" and "Bill length (mm)", respectively,
> *label the legend "Species"*

```{r penguins-8}
#| code-line-numbers: "18"
#| output-location: column
#| warning: false
ggplot(
  data = penguins,
  mapping = aes(
    x = bill_depth_mm,
    y = bill_length_mm
  )
) +
  geom_point(
    mapping = aes(color = species)
  ) +
  labs(
    title = "Bill depth and length",
    subtitle = paste("Dimensions for Adelie,",
                     "Chinstrap, and Gentoo",
                     "Penguins"),
    x = "Bill depth (mm)",
    y = "Bill length (mm)",
    color = "Species"
  ) 
```
:::


##

::: {.xsmall}
> Start with the `penguins` data frame,
> map bill depth to the x-axis
> and map bill length to the y-axis. 
> Represent each observation with a point
> and map species to the color of each point.
> Title the plot "Bill depth and length", 
> add the subtitle "Dimensions for Adelie, Chinstrap, and Gentoo Penguins", 
> label the x and y axes as "Bill depth (mm)" and "Bill length (mm)", respectively,
> label the legend "Species", 
> *and add a caption for the data source.*

```{r penguins-9}
#| code-line-numbers: "19"
#| output-location: column
#| warning: false
ggplot(
  data = penguins,
  mapping = aes(
    x = bill_depth_mm,
    y = bill_length_mm
  )
) +
  geom_point(
    mapping = aes(color = species)
  ) +
  labs(
    title = "Bill depth and length",
    subtitle = paste("Dimensions for Adelie,",
                     "Chinstrap, and Gentoo",
                     "Penguins"),
    x = "Bill depth (mm)",
    y = "Bill length (mm)",
    color = "Species",
    caption = "Source: palmerpenguins package"
  )
```
:::


##

::: {.xsmall}
> Start with the `penguins` data frame,
> map bill depth to the x-axis
> and map bill length to the y-axis. 
> Represent each observation with a point
> and map species to the color of each point.
> Title the plot "Bill depth and length", 
> add the subtitle "Dimensions for Adelie, Chinstrap, and Gentoo Penguins", 
> label the x and y axes as "Bill depth (mm)" and "Bill length (mm)", respectively,
> label the legend "Species", 
> and add a caption for the data source.
> *Finally, use the viridis color palette for all points.*

```{r penguins-10}
#| code-line-numbers: "21"
#| output-location: column
#| warning: false
ggplot(
    data = penguins,
    mapping = aes(
      x = bill_depth_mm,
      y = bill_length_mm
    )
  ) +
    geom_point(
      mapping = aes(color = species)
    ) +
    labs(
      title = "Bill depth and length",
      subtitle = paste("Dimensions for Adelie,",
                       "Chinstrap, and Gentoo",
                       "Penguins"),
      x = "Bill depth (mm)",
      y = "Bill length (mm)",
      color = "Species",
      caption = "Source: palmerpenguins package"
    ) +
    scale_color_viridis_d()
```
:::


# Aesthetics


## Aesthetics options

Commonly used characteristics of plotting geometries that can be **mapped to a specific variable** in the data, examples include:

- position (`x`, `y`)
- `color`
- `shape`
- `size`
- `alpha` (transparency)

Different geometries have different aesthetics available - see the [ggplot2 geoms](https://ggplot2.tidyverse.org/reference/index.html#Geoms) help files for listings.


* Aesthetics given in `ggplot()` apply to all `geom`s.

* Aesthetics for a specific `geom_*()` can be overridden via `mapping` or as an argument.


## color

::: {.xsmall}
```{r color}
#| out-width: 75%
ggplot(
  penguins, aes(x = bill_depth_mm, y = bill_length_mm)
) + 
  geom_point(
    aes(color = species)
  )
```
:::


## Stop the warning

::: {.xsmall}
```{r color_narm}
#| out-width: 75%
ggplot(
  penguins, aes(x = bill_depth_mm, y = bill_length_mm)
) + 
  geom_point(
    aes(color = species), na.rm=TRUE
  )
```
:::


## Shape

Mapped to a different variable than `color`

::: {.xsmall}
```{r shape-island}
#| out-width: 75%
ggplot(
  penguins, aes(x = bill_depth_mm, y = bill_length_mm)
) +
  geom_point(
    aes(color = species, shape = island), na.rm = TRUE
  )
```
:::



## Shape

Mapped to same variable as `color`

::: {.xsmall}
```{r shape-species}
#| out-width: 75%
ggplot(
  penguins, aes(x = bill_depth_mm, y = bill_length_mm)
) +
  geom_point(
    aes(color = species, shape = species), na.rm = TRUE
  )
```
:::



## Size

Using a fixed value - note that this value is outside of the `aes` call

::: {.xsmall}
```{r size1}
#| out-width: 66%
ggplot(
  penguins, aes(x = bill_depth_mm, y = bill_length_mm)
) +
  geom_point(
    aes(color = species, shape = species), na.rm = TRUE,
    size = 3
  )
```
:::



## Size

Mapped to a variable

::: {.xsmall}
```{r size2}
#| out-width: 66%
ggplot(
  penguins, aes(x = bill_depth_mm, y = bill_length_mm)
) +
  geom_point(
    aes(color = species, shape = species, size = body_mass_g), na.rm = TRUE
  )
```
:::



## Alpha

::: {.xsmall}
```{r alpha}
#| out-width: 75%
ggplot(
  penguins,
  aes(x = bill_depth_mm, y = bill_length_mm)
) +
  geom_point(
    aes(color = species, shape = species, alpha = body_mass_g), na.rm = TRUE,
    size = 3
  )
```
:::



## Mapping vs settings

- **Mapping** - Determine an aesthetic (the size, alpha, etc.) of a geom based on the values of a variable in the data
  - wrapped by `aes()` and pass as `mapping` argument to `ggplot()` or `geom_*()`.

<br/>

- **Setting** - Determine an aesthetic (the size, alpha, etc.) of a geom using a constant value not directly from the data.
  - passed directly into `geom_*()` as an argument.

. . .

<br/>

From the previous slide `color`, `shape`, and `alpha` are all **aesthetics** while `size` was a **setting**.



# Faceting


## Faceting

- Smaller plots that display different subsets of the data

- Useful for exploring conditional relationships and large data

- Sometimes referred to as "small multiples"


## facet_grid

::: {.xsmall}
```{r facet}
#| out-width: 75%
ggplot(
  penguins, aes(x = bill_depth_mm, y = bill_length_mm)
) + 
  geom_point(na.rm = TRUE) +
  facet_grid(
    species ~ island
  )  
```
:::


## Compare with ...

::: {.xsmall}
```{r facet_comp}
#| out-width: 75%
ggplot(
  penguins, aes(x = bill_depth_mm, y = bill_length_mm)
) + 
  geom_point(
    aes(color = species,shape = island), na.rm = TRUE, size = 3
  )
```
:::



## facet_grid (cols)

::: {.xsmall}
```{r facet2}
#| out-width: 75%
ggplot(
  penguins, aes(x = bill_depth_mm, y = bill_length_mm)
) + 
  geom_point(na.rm = TRUE) +
  facet_grid(
    ~ species
  )  
```
:::


## facet_grid (rows)

::: {.xsmall}
```{r facet3}
#| out-width: 75%
ggplot(
  penguins, aes(x = bill_depth_mm, y = bill_length_mm)
) + 
  geom_point(na.rm = TRUE) +
  facet_grid(
    species ~ .
  )  
```
:::


## facet_wrap

::: {.xsmall}
```{r facetwrap}
#| out-width: 75%
ggplot(
  penguins, aes(x = bill_depth_mm, y = bill_length_mm)
) + 
  geom_point(na.rm = TRUE) +
  facet_wrap(
    ~ species
  )
```
:::


## facet_wrap

::: {.xsmall}
```{r facetwrap2}
#| out-width: 75%
ggplot(
  penguins, aes(x = bill_depth_mm, y = bill_length_mm)
) + 
  geom_point(na.rm = TRUE) +
  facet_wrap(
    ~ species, ncol = 2
  )
```
:::



## Faceting and color

::: {.xsmall}
```{r facet-color-legend}
#| out-width: 75%
ggplot(
  penguins, aes(x = bill_depth_mm, y = bill_length_mm, color = species)
) +
  geom_point(na.rm = TRUE) +
  facet_grid(
    species ~ sex
  )
```
:::


## Hiding legend elements

::: {.xsmall}
```{r facet-color-no-legend}
#| out-width: 66%
ggplot(
  penguins, aes(x = bill_depth_mm, y = bill_length_mm, color = species)
) +
  geom_point(na.rm = TRUE) +
  facet_grid(
    species ~ sex
  ) +
  guides(color = "none")
```
:::



# A brief plot tour <br/> of ggplot2 plots

```{r}
#| include: false

knitr::opts_chunk$set(out.width="75%")
```

## Histograms

::: {.small}
```{r hist1, warning = FALSE}
ggplot(
  penguins, aes(x = body_mass_g)
) +
  geom_histogram()
```
:::

## Histograms - bins

::: {.small}
```{r hist3, warning = FALSE}
ggplot(
  penguins, aes( x = body_mass_g )
) +
  geom_histogram(bins = 50)
```
:::


## Histograms - binwidth

::: {.small}
```{r hist2, warning = FALSE}
ggplot(
  penguins, aes( x = body_mass_g )
) +
  geom_histogram(binwidth = 250)
```
:::




## Histograms - color

::: {.small}
```{r hist5, warning = FALSE}
ggplot(
  penguins, aes(x = body_mass_g, color = species)
) +
  geom_histogram(bins = 20)
```
:::


## Histograms - fill

::: {.small}
```{r hist4, warning = FALSE}
ggplot(
  penguins, aes(x = body_mass_g, fill = species)
) +
  geom_histogram(bins = 20)
```
:::


## Histograms - position

::: {.small}
```{r hist_pos, warning = FALSE}
#| out-width: 66%
ggplot(
  penguins, aes(x = body_mass_g, fill = species)
) + 
  geom_histogram(
    bins = 20, alpha = 0.5, position = "identity"
  )
```
:::



## Histograms - facets

::: {.small}   
```{r hist6, warning = FALSE}
#| out-width: 66%
ggplot(
  penguins, aes(x = body_mass_g, fill = species) 
) +
  geom_histogram(bins = 20) +
  facet_grid(species ~ .) + 
  guides(fill = "none")
```
:::


## Density plot

::: {.small}
```{r dens1, warning = FALSE}
ggplot(
  penguins, aes(x = body_mass_g)
) +
  geom_density()
```
:::


## Density plot - fill

::: {.small}
```{r dens3, warning = FALSE}
ggplot(
  penguins, aes(x = body_mass_g, fill = species)
) +
  geom_density(alpha = 0.25)
```
:::


## Density plot - adjust

::: {.small}
```{r dens2, warning = FALSE}
ggplot(
  penguins, aes(x = body_mass_g, fill = species)
) +
  geom_density(
    adjust = 0.5, alpha = 0.25
  )
```
:::


## Violin plot

::: {.small}
```{r violin, warning = FALSE}
ggplot(
  penguins, aes(x = species, fill = species, y = body_mass_g )
) +
  geom_violin()
```
:::


## Ridge plot

::: {.small}
```{r ridge, warning = FALSE}
ggplot(
  penguins, aes(x = body_mass_g, y = species, fill = species)
) +
  ggridges::geom_density_ridges(alpha = 0.5)
```
:::



## Ridge plot - more categories + dplyr

::: {.xsmall}
```{r ridge2, warning = FALSE}
#| out-width: 100%
penguins |>
  mutate( species_sex = paste0( species, " (", sex, ")") ) |>
  ggplot( aes(x = body_mass_g, y = species_sex, fill = species) ) +
  ggridges::geom_density_ridges( alpha = 0.5 )
```
:::



## Box plot

::: {.small}
```{r box1, warning = FALSE}
ggplot(
  penguins, aes(x = body_mass_g, y = species)
) +
  geom_boxplot()
```
:::


## Box plot - coord_flip

::: {.small}
```{r box2, warning = FALSE}
ggplot(
  penguins, aes(x = body_mass_g, y = species)
) +
  geom_boxplot() + 
  coord_flip()
```
:::


## Box plot - swap coords

::: {.small}
```{r box3, warning = FALSE}
ggplot(
  penguins, aes(x = species, y = body_mass_g)
) +
  geom_boxplot()
```
:::


## Scatter plot

::: {.small}
```{r scatter1, warning = FALSE}
ggplot(
  penguins, aes(x = bill_depth_mm, y = bill_length_mm, color = species)
) +
  geom_point() 
```
:::


## Scatter plot - geom_smooth

::: {.small}
```{r scatter3, warning = FALSE}
ggplot(
  penguins, 
  aes(x = bill_depth_mm, y = bill_length_mm, color = species)
) +
  geom_point() +
  geom_smooth( fullrange = TRUE )
```
:::

## Scatter plot - geom_smooth w/ lm

::: {.small}
```{r scatter2, warning = FALSE}
ggplot(
  penguins, aes(x = bill_depth_mm, y = bill_length_mm, color = species)
) +
  geom_point() +
  geom_smooth(
    method = "lm", se = FALSE, fullrange = TRUE
  )
```
:::




## Line plot

::: {.small}
```{r line, warning = FALSE}
#| out-width: 66%
penguins |>
  count(species, year) |>
  ggplot(
    aes(x = year, y = n, color = species, group = species)
  ) +
  geom_line()
```
:::


## Line plot - with points

::: {.small}
```{r line2, warning = FALSE}
#| out-width: 66%
penguins |>
  count(species, year) |>
  ggplot(
    aes(x = year, y = n, color = species, group = species)
  ) +
  geom_line() + 
  geom_point()
```
:::


## Bar plot

::: {.small}
```{r bar1, warning = FALSE}
ggplot(
  penguins, aes(x = species)
) +
  geom_bar()
```
:::


## Stacked bar plot

::: {.small}
```{r bar2, warning = FALSE}
ggplot(
  penguins, aes(x = species, fill = island)
) +
  geom_bar()
```
:::


## Stacked relative frequency bar plot

::: {.small}
```{r bar3, warning = FALSE}
ggplot(
  penguins, aes(x = species, fill = island)
) +
  geom_bar(position = "fill")
```
:::


## Dodged bar plot

::: {.small}
```{r bar4, warning = FALSE}
ggplot(
  penguins, aes(x = species,fill = sex)
) +
  geom_bar(position = "dodge")
```
:::


# Exercises

## Exercise 1

Recreate, as faithfully as possible, the following plot using ggplot2 and the `penguins` data.

```{r echo = FALSE, out.width = "60%", fig.height = 5}
penguins |>
  filter(!is.na(sex)) |>
  ggplot(
    aes(
      x = body_mass_g,
      fill = species
    ) 
  ) +
  geom_density(alpha = 0.5, color = NA) +
  facet_wrap(~sex, nrow = 2) + 
  labs(
    x = "Body Mass (g)",
    y = "",
    fill = "Species"
  )
```



## Exercise 2

Recreate, as faithfully as possible, the following plot from the `palmerpenguin` package README in ggplot2.

```{r echo = FALSE, out.width="55%"}
knitr::include_graphics("imgs/palmer_plot_ex2.png")
```

::: {.aside}
See the `palmerpenguins` pkgdown [site](https://allisonhorst.github.io/palmerpenguins/)
:::
