# packageslibrary(ggplot2)library(dplyr)library(tidyr)
# set global default themetheme_set(theme_minimal(base_size = 14))
<- presidential presidential_2
# Update the Bush name$name[8] <- "H.W.Bush" presidential_2$name[10] <- "W.Bush" presidential_2
Use Lines Segment and Rectangle Annotations in ggplot2 to Visualize U.S. Presidential Terms

In this article, we’ll visualize the continuity of US presidential terms from Dwight D. Eisenhower in 1953 to Donald Trump in 2021. Major techniques demonstrated in this article include:
- Reorder graphical elements (e.g., the y-axis)
- Create geometrical elements: line segments, texts, and rectangles
- Create format-enriched texts with
ggtext
package - Enrich texts with fonts from Google Fonts Repository
Data cleanup
In this article, we’ll use the presidential
dataset which is built in ggplot2. It shows the names of 12 U.S. presidents from Eisenhower to Trump, their start and end date of their terms, and their associated parties.
Reorder the president names by the start date. It consists two critical steps:
Arrange the rows by the start date. The arrangement proceeds in descending order (by
desc
), and early rows in the dataset will be plotted at the bottom of the plot.Convert the
name
variable to a nominal factor (noted as<fct>
in the printed output) to “memorize” the current order of president names.
<- presidential_2 %>% presidential_2.arranged arrange(desc(start)) %>% mutate(name = factor(name, levels = name))
# ready for visualization!head(presidential_2.arranged, n = 4)
Output:
# A tibble: 4 × 4
name start end party
<fct> <date> <date> <chr>
1 Trump 2017-01-20 2021-01-20 Republican
2 Obama 2009-01-20 2017-01-20 Democratic
3 W.Bush 2001-01-20 2009-01-20 Republican
4 Clinton 1993-01-20 2001-01-20 Democratic
For the code above, you may also use factor(name, levels = name, ordered = T)
to convert the name
variable to an ordered factor (indicated as <ord>
). In ggplot2 reordering, both a nominal <fct>
and an ordered factor <ord>
works the same. More details on ggplot2 graphic reordering from the basics to advanced skills can be found in this complete guide.
Visualization
Draw line segments to show the starting and ending year of the service terms of different Presidents. geom_segment()
requires four aesthetics: x
, y
for the staring coordinate, and xend
and yend
for the ending coordinate of the line segment.
<- presidential_2.arranged %>% p1 ggplot(aes(x = start, y = name, label = name, color = party, fill = party)) + geom_segment(aes(xend = end, yend = name), linewidth = 4) p1
Add president names. By default, the texts are center justified relative to the x
aesthetic (the starting year). Here instead, we use hjust
to change the justification rule. The elements of the hjust
vector is respectively applied to the president names in a bottom up order (from Trump to Eisenhower): the first value 0.3 shifts “Trump” to the left (so the text does not overflow beyond the plot boundary), and rep(0, 11)
left-justifies the other 11 names to the left edge of the line segment.
<- p1 + geom_text( p2 nudge_y = .35, fontface = "bold", hjust = c(.3, rep(0, 11))) p2
Add the years of serving terms.
<- p2 + geom_text( p3 # use format %Y to extract the year component from a Date aes(label = paste(format(start, "%Y"), "~", format(end, "%Y"))), nudge_y = -.35, hjust = c(.6, rep(0, 11)), size = 3.5) p3
Draw rectangles to highlight the serving terms and associated parties. geom_rect()
requires four aesthetics to specify the coordinates of the four edges, respectively: xmin
, xmax
, ymin
, and ymax
. Use the infinite value Inf
to draw rectangles extending across the entire axial range.
<- p3 + geom_rect( p4 aes(xmin = start, xmax = end, ymin = -Inf, ymax = Inf), alpha = .2, linewidth = .2, linetype = "dotted") p4
Adjust the color scale, plot aspect ratio, and themes.
# color scale of line segments and texts annotations<- c("Democratic" = "steelblue2", "Republican" = "firebrick1") myColors.light # color scale of the background<- c("Democratic" = "steelblue4", "Republican" = "firebrick4") myColors.dark
<- p4 + p5 # keep a long-narrow dimension coord_fixed(ratio = 2000, clip = "off") + # color / fill scale scale_color_manual(values = myColors.dark ) + scale_fill_manual(values = myColors.light) + theme_void() + theme(plot.margin = margin(rep(10, 4), unit = "pt"), legend.position = "none") p5
Add plot title with enriched colors using ggtext
package:
Use HTML in the title string. The line breaks in the script (make by pressing the Enter or return key) makes the script easier to read, but will not be visible in the rendered graphic. If you want to make an indicated line break, use
<br>
anywhere desired. Alternatively, you can use automatic text wrapping (see the following bullet)Use
element_textbox_simple()
intheme()
in place ofelement_text()
to render the HTML-masked title with automatic text wrapping. (Alternatively, useelement_markdown()
and HTML tag<br>
to make indicated line breaks, as in this example.)
library(ggtext)
<- c( plot_title "Presidential Chronicles: A Tale of <span style='color: steelblue3;'>Democrats</span> and <span style='color: red3;'>Republicans</span> from Eisenhower to Trump – Unveiling the Power Shifts in the U.S.")
<- p5 + ggtitle(plot_title) p6
+ p6 theme( plot.title = element_textbox_simple( margin = margin(b = 5, l = 20, r = 20, unit = "pt"), size = 14))
Load Google font “Anton” to further enhance the title. Use showtext
package to make it available to be used in ggplot2.
library(showtext)showtext_auto()font_add_google("Anton", "Anton")
+ p6 theme( plot.title = element_textbox_simple( margin = margin(b = 5, l = 20, r = 20, unit = "pt"), size = 14, # use Google font "Anton" family = "Anton"))
library(ggplot2)library(dplyr)library(tidyr)
# set global default themetheme_set(theme_minimal(base_size = 14))
<- presidential presidential_2
# Update the Bush name$name[8] <- "H.W.Bush" presidential_2$name[10] <- "W.Bush" presidential_2
# Reorder the president names by the start date<- presidential_2 %>% presidential_2.arranged arrange(desc(start)) %>% mutate(name = factor(name, levels = name))
# ready for visualization!head(presidential_2.arranged, n = 4)
# Draw line segments showing the starting and ending year of the terms. <- presidential_2.arranged %>% p1 ggplot(aes(x = start, y = name, label = name, color = party, fill = party)) + geom_segment(aes(xend = end, yend = name), linewidth = 4) p1
# Add president names<- p1 + geom_text( p2 nudge_y = .35, fontface = "bold", hjust = c(.3, rep(0, 11))) p2
# Add years of terms.<- p2 + geom_text( p3 # use format %Y to extract the year component from a Date aes(label = paste(format(start, "%Y"), "~", format(end, "%Y"))), nudge_y = -.35, hjust = c(.6, rep(0, 11)), size = 3.5) p3
# Draw rectangles to highlight the serving terms and associated parties.<- p3 + geom_rect( p4 aes(xmin = start, xmax = end, ymin = -Inf, ymax = Inf), alpha = .2, linewidth = .2, linetype = "dotted") p4
# Adjust the color scale, aspect ratio, and themes. ## color scale of line segments and texts annotations<- c("Democratic" = "steelblue2", "Republican" = "firebrick1") myColors.light ## color scale of the background<- c("Democratic" = "steelblue4", "Republican" = "firebrick4") myColors.dark
<- p4 + p5 # keep a long-narrow dimension coord_fixed(ratio = 2000, clip = "off") + # color / fill scale scale_color_manual(values = myColors.dark ) + scale_fill_manual(values = myColors.light) + theme_void() + theme(plot.margin = margin(rep(10, 4), unit = "pt"), legend.position = "none") p5
# Add plot title with enriched colorslibrary(ggtext)
<- c( plot_title "Presidential Chronicles: A Tale of <span style='color: steelblue3;'>Democrats</span> and <span style='color: red3;'>Republicans</span> from Eisenhower to Trump – Unveiling the Power Shifts in the U.S.")
<- p5 + ggtitle(plot_title) p6
+ p6 theme( plot.title = element_textbox_simple( margin = margin(b = 5, l = 20, r = 20, unit = "pt"), size = 14))
# Load Google font "Anton" to further enhance the title.library(showtext)showtext_auto()font_add_google("Anton", "Anton")
+ p6 theme( plot.title = element_textbox_simple( margin = margin(b = 5, l = 20, r = 20, unit = "pt"), size = 14, # use Google font "Anton" family = "Anton"))
Continue Exploring — 🚀 one level up!
Line segments when used properly can become powerful elements to aid in visualization, as demonstrated above. In addition, line segments can be readily updated into arrows to display information about trend of changes. The following article leverages annotated arrows in faceted panels to depict the changes in the proportion of seats held by women in national parliaments from 2000 to 2020.
Line segments can be readily combined with points to create dumbbell plots, useful to highlight items with contrast. In the following article, annotated dumbbell plots in faceted panels are employed to visualize the percentage of votes won by Donald Trump and Hillary Clinton from different population groups at the 2016 United States presidential election.