Skip to content

Instantly share code, notes, and snippets.

@yjunechoe
Last active December 8, 2021 10:22
Show Gist options
  • Save yjunechoe/b7bc540f290044ffebec0a9031d586df to your computer and use it in GitHub Desktop.
Save yjunechoe/b7bc540f290044ffebec0a9031d586df to your computer and use it in GitHub Desktop.
{ggplot2} flipbook for Phonetics Lab (10/23/20) - style guide & showcasing
---
title: "Visualizing Data (in R)"
subtitle: "An opinionated style guide"
author: "<br><br>June Choe<br><br>Phonetics Lab"
date: '2020-10-23'
output:
xaringan::moon_reader:
lib_dir: libs
css: [default, hygge, ninjutsu]
nature:
ratio: 16:10
highlightStyle: 'solarized-light'
highlightLines: true
countIncrementalSlides: false
editor_options:
chunk_output_type: console
---
```{css, echo = FALSE}
body {
font-family: Adelle;
}
a {
text-decoration: underline;
color: #23395B;
}
.inverse {
background-color: #23395B;
}
.remark-slide-content {
# background-color: #F9F9F9;
}
.remark-slide-content h1 {
font-size: 48;
}
strong, h1, h2, h3 {
color: #23395B;
}
.sc {
font-variant: small-caps;
}
.remark-code-line {
font-size: .8em;
line-height: 1.8em;
}
code.r.hljs.remark-code {
font-size: .8em;
line-height: 1.8em;
position: relative;
overflow-x: hidden;
color: black;
}
code.r.hljs.remark-code:hover {
overflow-x: visible;
width: 700px;
border-style: solid;
}
code.remark-inline-code {
font-family: Fira Code;
font-size: .8em;
}
.remark-slide-content{
padding-top: .5em;
padding-left: 3em;
}
.pull-left {
float: left;
width: 45%;
}
.pull-right {
float: right;
width: 49%;
}
```
```{r setup, echo = FALSE, message = FALSE, warning = FALSE}
library(tidyverse)
library(extrafont)
library(flipbookr)
library(xaringan)
library(xaringanExtra)
knitr::opts_chunk$set(fig.width = 6, message = FALSE, warning = FALSE, comment = " ", cache = F, dpi = 300)
set.seed(1234)
```
# Why?
--
**Why bother making your plots look nice?**
--
- <p>Helps people <strong>remember</strong> your results better</p>
--
- Makes your findings look more **credible**
--
- Increases the chance of your work being **shared**
--
- Shows **respect** for your audience
<br>
--
**Goal of this presentation**
--
- <p>Share practical tips for improving readability</p>
--
- Demonstrate implementations of these ideas (w/ [code](https://gist.github.com/yjunechoe/b7bc540f290044ffebec0a9031d586df))
---
# Outline
--
**Four practical tips for improving data visualizations**
--
- <p>Make your <strong>text</strong> readable</p>
--
- Be generous about **margins and spacing**
--
- Make your **legends** clear
--
- Make **color** easy on your reader's eyes
--
**Showcases**
--
- Vowel formant plot
- Vowel space plot
- Bar plot of proportions
- Multiple categorical levels
- Animations
---
# Preliminaries
.pull-left[
Work with the `{ggplot2}` ecosystem in R
- Widely used in academia
- Easy to use and highly customizable
- Tons of free resources for learning
- Lots of extensions
]
.pull-right[
```{r, echo=FALSE, out.width="400px", fig.align="right"}
knitr::include_graphics("https://d33wubrfki0l68.cloudfront.net/2c6239d311be6d037c251c71c3902792f8c4ddd2/12f67/css/images/hex/ggplot2.png")
```
]
---
# Preliminaries
.pull-left[
Work with the `{ggplot2}` ecosystem in R
- Widely used in academia
- Easy to use and highly customizable
- Tons of free resources for learning
- Lots of extensions
```{r, message = FALSE}
library(scales)
library(colorspace)
library(ggtext)
library(lemon)
library(gganimate)
# library(patchwork)
# library(gghighlight)
# library(ggforce)
# library(ggrepel)
```
]
.pull-right[
<iframe src="https://exts.ggplot2.tidyverse.org/gallery/" height="450px" width="510px">
]
---
# How does it work?
```{r, echo=FALSE, out.width="450px", fig.align="center", fig.cap="Source: https://www.youtube.com/watch?v=h29g21z0a68"}
knitr::include_graphics("P_lab_ggplot2_files/ggplot_layers.png")
```
---
```{r, echo = FALSE, message = FALSE, warning = FALSE}
state_election_votes <- read_csv("https://vincentarelbundock.github.io/Rdatasets/csv/pscl/presidentialElections.csv") %>%
select(State = state, demVote, Year = year) %>%
mutate(demVote = round(demVote/100, 2))
```
```{r example-1, include = FALSE, dpi = 75}
state_election_votes %>%
filter(State %in%
c("Pennsylvania",
"Illinois",
"California")
) %>%
ggplot() +
aes(
x = Year,
y = demVote,
color = State
) +
geom_point() + #OMIT
geom_point() + #ROTATE
geom_line() + #ROTATE
geom_line(size = 1) + #ROTATE
scale_y_continuous(
labels = percent_format(accuracy = 1)
) +
scale_x_continuous(
breaks = pretty_breaks(n= 5)
) +
labs(
y = "Democrat Votes",
title = "Go Vote!"
)
```
`r chunk_reveal("example-1", omit = "#ROTATE", break_type = "auto", widths = c(40, 60))`
---
`r chunk_reveal("example-1", omit = "#OMIT", break_type = "rotate", widths = c(40, 60))`
---
# Yay a plot!
```{r, echo = FALSE, dpi = 75}
state_election_plot <- state_election_votes %>%
filter(State %in%
c("Pennsylvania",
"Illinois",
"California")
) %>%
ggplot() +
aes(
x = Year,
y = demVote,
color = State
) +
geom_line(size = 1) +
scale_y_continuous(
labels = percent_format(accuracy = 1)
) +
scale_x_continuous(
breaks = pretty_breaks(n= 5)
) +
labs(
y = "Percent of Democrat Votes",
title = "Go Vote!"
)
```
.pull-left[
```{r state_election_plot, echo = FALSE, fig.align="center", out.height="450px", dpi = 75}
state_election_plot
```
]
.pull-right[
]
---
# Yay a plot... ?
.pull-left[
```{r state_election_plot, echo = FALSE, fig.align="center", out.height="450px", dpi = 100}
```
]
.pull-right[
**A few problems**
- Text is small and narrow
- Plot elements are squished together
- Color doesn't grab attention
- Legend is off to the side on its own
]
---
#1. Text
Many different ways to style text:
--
- <p><span style="font-size: .7em">font</span> <span style="font-size: 1.5em">size</span></p>
--
- Font face (<strong style="color:black">bold</strong>, *italic*, <span style="font-variant: small-caps">small caps</span>)
--
- Font family (<span style="font-family: Times New Roman"> Times New Roman</span>, <span style="font-family: Calibri"> Calibri</span>, <span style="font-family: Arial"> Arial</span>, <span style="font-family: Wingdings">Hi friends</span> )
--
- Font color, line height, letter spacing, angle, weight, etc.
--
<br>
Unless you make your plots with html/css/js, you'll likely only have access to:
--
- <p>Font size, font family, and limited set of font styles</p>
--
- But you can get pretty far with these!
---
```{r text, echo = FALSE, eval = FALSE}
state_election_plot +
theme(text = element_text(family = "Roboto")) + #OMIT
theme(text = element_text(family = "Adelle")) + #ROTATE
theme(text = element_text(family = "Bitter")) + #ROTATE
theme(text = element_text(family = "Futura Bk BT")) + #ROTATE
theme(text = element_text(family = "Montserrat")) + #ROTATE
theme(text = element_text(family = "Montserrat Medium")) + #ROTATE
theme(text = element_text(family = "Arial")) + #ROTATE
theme(text = element_text(family = "xkcd")) + #ROTATE
theme(text = element_text(size = 15)) +
theme(plot.title = element_text(size = 20)) +
theme(plot.title = element_text(family = "Roboto Slab")) +
theme(plot.title.position = "plot") +
labs(x = "Election Year") +
labs(y = NULL) +
labs(title = "Percent of democrat votes by state") +
labs(subtitle = "We're a swing state! Go vote!") +
theme(plot.subtitle = element_text(face = "italic"))
```
`r chunk_reveal("text", omit = "#ROTATE", break_type = "auto", widths = c(40, 60))`
---
`r chunk_reveal("text", omit = "#OMIT", break_type = "rotate", widths = c(40, 60))`
---
#1. Text (End!)
.pull-left[
```{r, echo = FALSE}
state_election_plot_A <- state_election_plot +
theme(
text = element_text(size = 16, family = "Roboto"),
plot.title = element_text(size = 20, family = "Roboto Slab"),
plot.title.position = "plot",
plot.subtitle = element_text(face = "italic"),
axis.text = element_text(size = 14)
) +
labs(
x = "Election Year",
y = NULL,
title = "Percent of democrat votes by state",
subtitle = "We're a swing state! Go vote!"
)
```
```{r text_final, eval = FALSE}
state_election_plot +
theme(
text = element_text(size = 16, family = "Roboto"),
plot.title = element_text(size = 20, family = "Roboto Slab"),
plot.title.position = "plot",
plot.subtitle = element_text(face = "italic"),
axis.text = element_text(size = 14)
) +
labs(
x = "Election Year",
y = NULL,
title = "Percent of democrat votes by state",
subtitle = "We're a swing state! Go vote!"
)
```
Save our progress!
```{r, eval = FALSE}
state_election_plot_A
```
]
.pull-right[
```{r text_final, echo = FALSE, out.width = "400px"}
```
]
---
#1. Text (Before-After)
.pull-left[
```{r, echo = FALSE, out.width = "400px"}
state_election_plot
```
]
.pull-right[
```{r, echo = FALSE, out.width = "400px"}
state_election_plot_A
```
]
---
#2. Margins & Spacing
```{r, echo = FALSE, out.height = "450px", fig.align="center"}
state_election_plot_A
```
---
#2. Margins & Spacing
```{r, echo = FALSE, out.height = "450px", fig.align="center"}
state_election_plot_A +
theme(
plot.background = element_rect(color = "black", size = 1)
)
```
---
#2. Margins & Spacing
```{r, echo = FALSE, out.height = "450px", fig.align="center"}
state_election_plot_A +
theme(
plot.background = element_rect(color = "black", fill = "#FFFF88", size = 1)
)
```
---
#2. Margins & Spacing
Base {ggplot2} themes don't have _great_ margin defaults for:
--
- <p>Margins around plot</p>
--
- Margins between plot title and panel
--
- Margins between axis titles and panel
--
- Margins between axis texts and axis title
--
<br>
Know your margin/spacing elements!
- `margin(t = 0, r = 0, b = 0, l = 0, unit = c("pt", "mm", "cm", "in"))`
- `hjust`, `vjust`, and `lineheight` in `element_text()`
- `expand` in `scale_*()`/`coord_*()`
---
```{r margins, echo = FALSE, eval = FALSE, warning = FALSE}
state_election_plot_A +
theme(
plot.background = element_rect(color = 'black')
) +
theme(
plot.margin = margin(1, .8, .8, .8, "cm")
) +
theme(
plot.title = element_text(margin = margin(b = .3, unit = "cm"))
) +
theme(
plot.subtitle = element_text(margin = margin(b = .3, unit = "cm"))
) +
theme(
axis.text.x = element_text(margin = margin(t = .2, unit = "cm"))
) +
theme(
axis.text.y = element_text(margin = margin(r = .1, unit = "cm"))
) +
theme(
axis.title.x = element_text(margin = margin(t = .3, unit = "cm"))
) +
coord_cartesian(expand = FALSE) + #OMIT
scale_x_continuous(expand = expansion(mult = 0, add = 3)) + #ROTATE
scale_x_continuous(expand = expansion(mult = 0, add = 3), breaks = pretty_breaks(5)) #ROTATE
```
`r chunk_reveal("margins", omit = "#ROTATE", break_type = "auto", widths = c(40, 60))`
---
`r chunk_reveal("margins", omit = "#OMIT", break_type = "rotate", widths = c(40, 60))`
---
#2. Margins & Spacing (End!)
.pull-left[
```{r, echo = FALSE, message = FALSE}
state_election_plot_B <- state_election_plot_A +
theme(
plot.margin = margin(1, .8, .8, .8, "cm"),
plot.title = element_text(margin = margin(b = .3, unit = "cm")),
plot.subtitle = element_text(margin = margin(b = .3, unit = "cm")),
axis.text.x = element_text(margin = margin(t = .2, unit = "cm")),
axis.text.y = element_text(margin = margin(r = .1, unit = "cm")),
axis.title.x = element_text(margin = margin(t = .3, unit = "cm"))
) +
scale_x_continuous(
expand = expansion(mult = 0, add = 3),
breaks = pretty_breaks(5)
)
```
```{r margins_final, eval = FALSE}
state_election_plot_A +
theme(
plot.margin = margin(1, .8, .8, .8, "cm"),
plot.title = element_text(margin = margin(b = .3, unit = "cm")),
plot.subtitle = element_text(margin = margin(b = .3, unit = "cm")),
axis.text.x = element_text(margin = margin(t = .2, unit = "cm")),
axis.text.y = element_text(margin = margin(r = .1, unit = "cm")),
axis.title.x = element_text(margin = margin(t = .3, unit = "cm"))
) +
scale_x_continuous(
expand = expansion(mult = 0, add = 3),
breaks = pretty_breaks(5)
)
```
Save our progress!
```{r, eval = FALSE}
state_election_plot_B
```
]
.pull-right[
```{r margins_final, echo = FALSE, out.width = "400px"}
```
]
---
#2. Margins & Spacing (Before-After)
.pull-left[
```{r, echo = FALSE, out.width = "400px"}
state_election_plot_A
```
]
.pull-right[
```{r, echo = FALSE, out.width = "400px"}
state_election_plot_B
```
]
---
class: inverse
#2. Margins & Spacing (Before-After)
.pull-left[
```{r, echo = FALSE, out.width = "400px"}
state_election_plot_A
```
]
.pull-right[
```{r, echo = FALSE, out.width = "400px"}
state_election_plot_B
```
]
---
#3. Legends
--
Legends are really hard:
--
- <p>They contain important info, but difficult to make them not look out of place</p>
--
- It's better not to have a legend, if you can get away with it
--
- But sometimes we don't have the luxury of doing so
--
<br>
Alternative: consider _labeling the data directly_
---
class: inverse, center, middle
```{r, echo = FALSE, out.width="550px"}
knitr::include_graphics("P_lab_ggplot2_files/538plots.gif")
```
---
#3. Legends
Legends are really hard:
- <p>They contain important info, but difficult to make them not look out of place</p>
- It's better not to have a legend, if you can get away with it
- But sometimes we don't have the luxury of doing so
<br>
Alternative: consider _labeling the data directly_
--
<br>
But if you must have a legend, make it so that the reader **_can't help_** but to look at
--
- <p>Positioned at the top-left or top-center of the plot</p>
--
- Blend smoothly into the rest of the plot (_NOT_ make them stand out!)
---
```{r legends2, echo = FALSE, eval = FALSE, warning = FALSE}
state_election_plot_B +
theme(
legend.key = element_rect(fill = NA)
) +
theme(
legend.position = c(.45, .93)
) +
theme(
legend.direction = "horizontal"
) +
theme(
legend.background = element_rect(fill = "grey92")
) +
scale_y_continuous(
expand = expansion(0, .05),
labels = percent_format(accuracy = 1)
) +
labs(color = NULL)
```
`r chunk_reveal("legends2", break_type = "auto", widths = c(40, 60))`
---
#3. Legends (End!)
.pull-left[
```{r, echo = FALSE, message = FALSE}
state_election_plot_C <- state_election_plot_B +
theme(
legend.key = element_rect(fill = NA),
legend.position = c(.45, .93),
legend.direction = "horizontal",
legend.background = element_rect(fill = "grey92")
) +
scale_y_continuous(
expand = expansion(0, .05),
labels = percent_format(accuracy = 1)
) +
labs(color = NULL)
```
```{r legends_final, eval = FALSE}
state_election_plot_B +
theme(
legend.key = element_rect(fill = NA),
legend.position = c(.45, .93),
legend.direction = "horizontal",
legend.background = element_rect(fill = "grey92")
) +
scale_y_continuous(
expand = expansion(0, .05),
labels = percent_format(accuracy = 1)
) +
labs(color = NULL)
```
Save our progress!
```{r, eval = FALSE}
state_election_plot_C
```
]
.pull-right[
```{r legends_final, echo = FALSE, out.width = "400px"}
```
]
---
#3. Legends (Before-After)
.pull-left[
```{r, echo = FALSE, out.width = "400px"}
state_election_plot_B
```
]
.pull-right[
```{r, echo = FALSE, out.width = "400px"}
state_election_plot_C
```
]
---
#4. Color
--
Colors are a double-edged sword
--
- <p>Perception can vary widely depending on reader, medium, culture, etc.</p>
--
- There are multiple, complex representations (RGB, wavelength, hex, [HSV](https://colordesigner.io/convert/hextohsv))
---
class: center, middle
```{r, echo = FALSE, out.width = "600px"}
knitr::include_graphics("https://yjunechoe.github.io/posts/2020-10-22-analysis-of-everycolorbots-tweets/HSV.png")
```
---
#4. Color
Colors are a double-edged sword
- Perception can vary widely depending on reader, medium, culture, etc.
- There are multiple, complex representations (RGB, wavelength, hex, [HSV](https://colordesigner.io/convert/hextohsv))
--
<br>
If you must, DO:
--
- <p>Avoid pure colors (no random sampling from the rainbow!)</p>
--
- Contrast colors in more than one dimension
---
class: center, middle
```{r, echo = FALSE, out.width = "650px"}
knitr::include_graphics("P_lab_ggplot2_files/avoid_pure_colors.png")
```
<br>
source: https://blog.datawrapper.de/beautifulcolors/
---
class: center, middle
```{r, echo = FALSE, out.width = "650px"}
knitr::include_graphics("P_lab_ggplot2_files/combine_diff_dimensions.png")
```
<br>
source: https://blog.datawrapper.de/beautifulcolors/
---
#4. Color
Colors are a double-edged sword
- Perception can vary widely depending on reader, medium, culture, etc.
- There are multiple, complex representations (RGB, wavelength, hex, [HSV](https://colordesigner.io/convert/hextohsv))
<br>
If you must, DO:
- Avoid pure colors (no random sampling from the rainbow!)
- Contrast colors in more than one dimension
<br>
If you aren't sure, use [pre-made palettes](https://github.com/EmilHvitfeldt/paletteer) or play around with [online color tools](https://color.adobe.com/create/color-wheel)
---
class: center, middle
<iframe src="https://paletton.com/" height="600px" width="1050px">
---
```{r colors1, echo = FALSE, eval = FALSE, warning = FALSE}
state_election_plot_C +
theme(panel.background = element_rect(fill = NA)) +
theme(legend.background = element_rect(fill = NA)) +
theme(axis.line = element_line()) +
scale_color_manual(
values = c("#F8766D", "#00BA38", "#619CFF")
) +
scale_color_manual(
values = c(
hex(HSV( 4, 0.56, 0.97)),
hex(HSV(138, 1, 0.73)),
hex(HSV(218, 0.62, 1))
)
) +
scale_color_manual(
values = c(
hex(HSV( 0, 1, 1)),
hex(HSV(120, 1, 1)),
hex(HSV(210, 1, 1))
)
) +
scale_color_manual(
values = c(
hex(HSV( 42, 0.56, 0.84)),
hex(HSV(133, 0.17, 0.57)),
hex(HSV(205, 0.75, 0.51))
)
) +
scale_color_manual(
values = c("#D6B25E", "#79917E", "#215982")
) +
geom_line(size = 1.5)
```
`r chunk_reveal("colors1", break_type = "auto", widths = c(40, 60))`
---
```{r, eval=FALSE}
library(colorBlindness)
```
<br>
```{r, echo = FALSE, fig.align="center", out.width="850px"}
knitr::include_graphics("P_lab_ggplot2_files/CBplot.png")
```
```{r, echo = FALSE, eval = FALSE}
colorblind_plot <- state_election_plot_C +
theme(panel.background = element_rect(fill = NA)) +
theme(legend.background = element_rect(fill = NA)) +
theme(axis.line = element_line()) +
scale_color_manual(
values = c("#D6B25E", "#79917E", "#215982")
) +
geom_line(size = 0.5) +
theme(legend.position = 0) +
theme(text = element_text(size = 12),
plot.title = element_text(size = 14),
plot.margin = margin(5, 5,0,0, "mm")
)
colorBlindness::cvdPlot(colorblind_plot)
```
---
```{r themes, echo = FALSE, eval = FALSE}
state_election_plot_C +
theme(panel.background = element_rect(fill = NA)) +
theme(legend.background = element_rect(fill = NA)) +
theme(axis.line = element_line()) +
geom_line(size = 1.5) +
ggthemes::scale_color_colorblind() + #ROTATE
nord::scale_color_nord(palette = "aurora", discrete = TRUE) + #ROTATE
ggsci::scale_color_simpsons() + #ROTATE
ghibli::scale_color_ghibli_d("SpiritedDark", direction = -1) + #ROTATE
scale_color_manual(values = wesanderson::wes_palette("Moonrise2", 3, "discrete")) + #ROTATE
palettetown::scale_color_poke(pokemon = "pikachu") + #ROTATE
scale_color_manual(values = LaCroixColoR::lacroix_palette("PeachPear", 3, "discrete")) #ROTATE
```
`r chunk_reveal("themes", break_type = "rotate", widths = c(40, 60))`
---
```{r colors2, echo = FALSE, eval = FALSE, warning = FALSE}
state_election_plot_C +
theme(
panel.background = element_rect(fill = NA)
) +
theme(
legend.background = element_rect(fill = NA)
) +
theme(
axis.line = element_line()
) +
scale_color_manual(
values = c("#e1e1e1", "#e1e1e1", "#2b5e82")
) +
guides(
color = guide_none()
) +
labs(subtitle = "<span style='color:#2b5e82'>Pennsylvania</span> is a swing state! Go vote!") + #OMIT
labs(subtitle = "<span style='color:#0E4369'>Pennsylvania</span> is a swing state! Go vote!") + #ROTATE
labs(subtitle = "<strong style='color:#0E4369'>Pennsylvania</strong> is a swing state! Go vote!") + #ROTATE
theme(
plot.subtitle = ggtext::element_markdown()
) +
geom_line(size = 1.5)
```
`r chunk_reveal("colors2", omit = "#ROTATE", break_type = "auto", widths = c(40, 60))`
---
`r chunk_reveal("colors2", omit = "#OMIT", break_type = "rotate", widths = c(40, 60))`
---
#4. Colors (End!)
.pull-left[
```{r, echo = FALSE, message = FALSE}
state_election_plot_D <- state_election_plot_C +
geom_line(size = 1.5) +
theme(
panel.background = element_rect(fill = NA),
legend.background = element_rect(fill = NA),
axis.line = element_line(),
plot.subtitle = element_markdown()
) +
guides(color = guide_none()) +
scale_color_manual(values = c("#e1e1e1", "#e1e1e1", "#2b5e82")) +
labs(subtitle = "<strong style='color:#0E4369'>Pennsylvania</strong> is a swing state! Go vote!")
```
```{r colors_final, eval = FALSE}
state_election_plot_C +
geom_line(size = 1.5) +
theme(
panel.background = element_rect(fill = NA),
legend.background = element_rect(fill = NA),
axis.line = element_line(),
plot.subtitle = element_markdown()
) +
guides(color = guide_none()) +
scale_color_manual(values = c("#e1e1e1", "#e1e1e1", "#2b5e82")) +
labs(
subtitle = "<strong style='color:#0E4369'>Pennsylvania</strong>
is a swing state! Go vote!"
)
```
Save our progress!
```{r, eval = FALSE}
state_election_plot_D
```
]
.pull-right[
```{r colors_final, echo = FALSE, out.width = "400px"}
```
]
---
#4. Colors (Before-After)
.pull-left[
```{r, echo = FALSE, out.width = "400px"}
state_election_plot_C
```
]
.pull-right[
```{r colors1, echo = FALSE, out.width = "400px"}
```
]
---
#4. Colors (Before-After)
.pull-left[
```{r, echo = FALSE, out.width = "400px"}
state_election_plot_C
```
]
.pull-right[
```{r, echo = FALSE, out.width = "400px"}
state_election_plot_D
```
]
---
class: inverse, center, middle
```{r, echo = FALSE, out.width="500px"}
knitr::include_graphics("P_lab_ggplot2_files/final.gif")
```
---
```{r final, echo=FALSE, eval = FALSE}
state_election_plot +
theme_classic(
base_family = "Roboto",
base_size = 16
) +
guides(color = guide_none()) +
geom_line(size = 1.5) +
scale_color_manual(
values = c("#e1e1e1", "#e1e1e1", "#2b5e82")
) +
labs(
y = NULL,
x = "Election Year",
title = "Percent of democrat votes by state",
subtitle = "<strong style='color:#0E4369'>Pennsylvania</strong> is a swing state! Go vote!"
) +
theme(
plot.margin = margin(.8, 1, .7, .8, "cm"),
plot.title = element_text(
family = "Roboto Slab",
size = 24,
margin = margin(b = .3, unit = "cm")
),
plot.title.position = "plot",
plot.subtitle = element_markdown(
margin = margin(b = .3, unit = "cm")
),
axis.title.x = element_text(
margin = margin(t = .5, unit = "cm")
),
)
```
`r chunk_reveal("final", break_type = "auto", widths = c(40, 60))`
---
class: inverse, center, middle
# Showcasing
---
# First, save our theme!
.pull-left[
You can set global theme with `theme_set()` and `theme_update()`:
<br>
- `theme_set()` takes a custom theme as a argument (e.g., `theme_bw()`, `theme_classic()`, etc.)
<br>
- `theme_update()` takes individual theme elements as arguments
<br>
]
.pull-right[
```{r}
theme_set(
theme_classic(
base_family = "Roboto",
base_size = 16
)
)
theme_update(
plot.margin = margin(.8, 1, .7, .8, "cm"),
plot.title = element_text(
family = "Roboto Slab",
size = 24,
margin = margin(b = .5, unit = "cm")
),
plot.title.position = "plot",
axis.title.x = element_text(
margin = margin(t = .5, unit = "cm")
)
)
```
]
---
class: inverse, center, middle
## 1. Vowel Formant Plot
```{r vowel_data, echo = FALSE}
library(rvest)
sim_vowel_scraped_all <- read_html('https://en.wikipedia.org/wiki/Formant') %>%
html_node(xpath = '/html/body/div[3]/div[3]/div[5]/div[1]/table[2]') %>%
html_table() %>%
select(1:3) %>%
rename_all(~c("Vowel", "F1", "F2")) %>%
as_tibble()
sim_vowel_data_all <- sim_vowel_scraped_all %>%
mutate(data = map2(F1, F2,
~ MASS::mvrnorm(
50, mu = c(F1 = .x, F2 = .y),
Sigma = matrix(
c(80^2, 80*150*runif(1, -.5, .5),
80*150*runif(1, -.5, .5), 150^2),
nrow = 2)
) %>%
as_tibble() %>%
modify(abs)
)
) %>%
select(-c(F1, F2)) %>%
unnest(data)
sim_vowel_data <- sim_vowel_data_all %>%
filter(Vowel %in% c("i", "e", "ɛ", "œ", "a", "ɑ", "ʌ", "ɔ", "o", "u"))
```
---
```{r vowels1, echo = FALSE, eval=FALSE, fig.height=5, fig.width=7}
sim_vowel_data %>%
ggplot(aes(x = F2, y = F1)) +
geom_text(aes(label = Vowel)) +
scale_x_reverse(
position = "top",
breaks = pretty_breaks(5)
) +
scale_y_reverse(position = "right") +
theme(
plot.margin = margin(.5,.5, 1, 1, unit = "cm"),
axis.title.x.top = element_text(margin = margin(b = .2, unit = "cm")),
axis.title.y.right = element_text(
angle = 0, vjust = 0.5, margin = margin(l = .3, unit = "cm")
)
) +
stat_ellipse(aes(group = Vowel))
```
`r chunk_reveal("vowels1", break_type = "auto", widths = c(40, 60))`
---
class: inverse, center, middle
# 2. Vowel Space Plot
```{r stat_chull, echo = FALSE}
StatChull <- ggproto("StatChull", Stat,
compute_group = function(data, scales) {
data[chull(data$x, data$y), , drop = FALSE]
},
required_aes = c("x", "y")
)
stat_chull <- function(mapping = NULL, data = NULL, geom = "polygon",
position = "identity", na.rm = FALSE, show.legend = NA,
inherit.aes = TRUE, ...) {
layer(
stat = StatChull, data = data, mapping = mapping, geom = geom,
position = position, show.legend = show.legend, inherit.aes = inherit.aes,
params = list(na.rm = na.rm, ...)
)
}
```
---
```{r vowels2, echo = FALSE, eval=FALSE}
sim_vowel_data_all %>%
group_by(Vowel) %>%
summarize(across(c(F1, F2), mean), .groups = 'drop') %>%
ggplot(aes(x = F2, y = F1)) +
geom_text(aes(label = Vowel), size = 6, family = "Charis SIL") +
scale_x_reverse(
position = "top",
breaks = pretty_breaks(5),
expand = expansion(.1)
) +
scale_y_reverse(
position = "right",
expand = expansion(.1)
) +
theme(
plot.margin = margin(.5,.5, 1, 1, unit = "cm"),
axis.title.x.top = element_text(margin = margin(b = .2, unit = "cm")),
axis.title.y.right = element_text(
angle = 0, vjust = 0.5, margin = margin(l = .3, unit = "cm")
)
) +
stat_chull(
fill = NA,
color = "black",
linetype = 2
)
```
`r chunk_reveal("vowels2", break_type = "auto", widths = c(40, 60))`
---
class: inverse, center, middle
# 3. Bar Plot of Proportions
---
```{r accuracy_bar, echo = FALSE, eval=FALSE}
read_csv("https://raw.githubusercontent.com/yjunechoe/Semantic-Persistence/master/processed.csv") %>%
filter(Type == "Critical") %>%
group_by(Cond, Group) %>%
summarize(Accuracy = mean(Accuracy, na.rm = TRUE), .groups = 'drop') %>%
ggplot(aes(x = Cond, y = Accuracy, fill = Group)) +
geom_col(position = "dodge", color = "white", width = .7, size = 2) +
scale_fill_manual(values = c("grey30", "grey70")) +
labs(
title = "Accuracy on Comprehension Task",
x = "Pitch Accent Condition", y = NULL,
fill = "Experiment Group"
) +
guides(fill = guide_legend(direction = "horizontal", title.position = "top")) +
coord_capped_cart(
ylim = c(0.5, 1),
left = "top"
) +
theme(
axis.ticks.x = element_blank(),
axis.text.x = element_text(color = "black", margin = margin(t = .2, unit = "cm")),
legend.position = c(.3, .93),
plot.title = element_text(margin = margin(b = 1, unit = "cm"))
) +
scale_y_continuous(
expand = expansion(0, 0),
labels = percent_format(accuracy = 1)
)
```
`r chunk_reveal("accuracy_bar", break_type = "auto", widths = c(40, 60))`
---
class: inverse, center, middle
# 4. Multiple Categorical Levels
---
class: center, middle
```{r, echo = FALSE, out.height="500px"}
knitr::include_graphics("https://yjunechoe.github.io/posts/2020-09-20-plot-makeover-1/plot.png")
```
Source: [Husband & Patson (2020)](https://amlap2020.github.io/a/272.pdf)
---
.pull-left[
```{r makeover, message = FALSE, eval=FALSE}
df <- crossing(level_1 = fct_inorder(c("Within", "Between")),
level_2 = fct_inorder(c("Some", "Number", "Or")),
level_3 = factor(c("Strong", "Weak")))
df$barheight <- c(.63, .35, .72, .55, .61, .15, .60, .55, .52, .63, .17, .16)
df %>%
ggplot(aes(level_3, barheight)) +
geom_col(
aes(fill = level_3),
show.legend = FALSE
) +
geom_errorbar(
aes(ymin = barheight - .05, ymax = barheight + .05),
width = .1) +
facet_grid(level_2 ~ level_1) +
theme_bw() +
scale_fill_manual(values = c('grey40', 'grey80')) +
ylim(0, 1) +
labs(
y = "Proportion of Strong Responses",
x = "Prime Type") +
theme_bw()
```
]
.pull-right[
```{r, echo = FALSE, out.width="350px"}
knitr::include_graphics("https://yjunechoe.github.io/posts/2020-09-20-plot-makeover-1/plot-makeover-1_files/figure-html5/unnamed-chunk-3-1.png")
```
]
---
class: center, middle
```{r, echo = FALSE, out.height="500px"}
knitr::include_graphics("https://yjunechoe.github.io/posts/2020-09-20-plot-makeover-1/plot-makeover-1_files/figure-html5/after_bar_plot-1.png")
```
([Code](https://yjunechoe.github.io/posts/2020-09-20-plot-makeover-1/))
---
class: center, middle
```{r, echo = FALSE, out.height="500px"}
knitr::include_graphics("https://yjunechoe.github.io/posts/2020-09-20-plot-makeover-1/plot-makeover-1_files/figure-html5/after_pointplot-1.png")
```
([Code](https://yjunechoe.github.io/posts/2020-09-20-plot-makeover-1/))
---
class: inverse, center, middle
# 5. Animations: Vowel shift
---
.pull-left[
```{r canada, message = FALSE, eval=FALSE}
read_csv("https://raw.githubusercontent.com/bodowinter/canadian_vowel_shift_analysis/master/processed_data/production_processed.csv") %>%
group_by(Gender, Vowel, BirthDecade = 10 * BirthYear %/% 10) %>%
summarize(across(F1:F2, mean), .groups = 'drop') %>%
filter(Gender == "F") %>%
ggplot(aes(F2, F1)) +
geom_text(aes(1450, 615, label = as.character(BirthDecade)),
color = "gray80", size = 48) +
stat_chull(fill = NA, color = "black", linetype = 2) +
geom_label(aes(label = Vowel), size = 6, family = "Charis SIL") +
scale_x_reverse(position = "top") +
scale_y_reverse(position = "right") +
theme(
plot.margin = margin(.5,.8, 1.2, 1, unit = "cm"),
axis.title.x.top = element_text(margin = margin(b = .2, unit = "cm")),
axis.title.y.right = element_text(angle = 0, vjust = 0.5, margin = margin(l = .3, unit = "cm"))
) +
coord_cartesian(clip = 'off') +
labs(title = "Canadian Vowel Shift", caption = "Source: Kettig & Winter (2017)") +
transition_states(BirthDecade) +
shadow_mark(
alpha = .1,
color = "grey",
exclude_layer = c(1, 2)
)
```
]
.pull-right[
<br>
<br>
```{r, echo = FALSE, out.width="500px"}
knitr::include_graphics("P_lab_ggplot2_files/canada_vowel_shift.gif")
```
]
---
class: inverse, center, middle
# 5. Animations: Eye-tracking
---
class: center, middle
```{r, echo = FALSE, out.height="500px", fig.cap="de Carvalho et al. (2017)"}
knitr::include_graphics("P_lab_ggplot2_files/eyetrack_original.png")
```
---
class: center, middle
```{r, echo = FALSE, out.height="500px"}
knitr::include_graphics("https://yjunechoe.github.io/static/dataviz/eyetracking_anim.gif")
```
([Code](https://gist.github.com/yjunechoe/b39e92889768b26faaec3e0103d4af10))
---
# Resources
<span style = "font-variant: small-caps;">light</span>
- [The Glamour of Graphics](https://rstudio.com/resources/rstudioconf-2020/the-glamour-of-graphics/) (20-min video)
- [Gallery of plot tyes](https://www.data-to-viz.com/)
- [What to consider when choosing colors for data viz](https://blog.datawrapper.de/colors/)
- [Palettes (in R)](https://github.com/EmilHvitfeldt/r-color-palettes)
<span style = "font-variant: small-caps;">heavy</span>
- [Font Recommendations](https://practicaltypography.com/font-recommendations.html) (book chapter)
- [Theme elements in ggplot2](https://ggplot2.tidyverse.org/reference/theme.html) (documentation)
- [ggplot2 tutorial](https://www.youtube.com/watch?v=h29g21z0a68) (4-hour video, 2 parts)
- [ggplot2 book](https://ggplot2-book.org/)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment