The ggtext package enables the rendering of complex
formatted plot labels (titles, subtitles, facet labels, axis labels,
etc.). Text boxes with automatic word wrap are also supported. It
defines two new theme elements, element_markdown()
and
element_textbox()
(element_textbox_simple()
),
which can be used in place of element_text() in ggplot2 themes.
R codes for creating the plot:
# Clear our R environment:
rm(list = ls())
# Import readxl for loading xlsx files:
library(readxl)
library(dplyr)
# Load data (download from: https://drive.google.com/file/d/1AC70gyMQO0TufMJa1VCc5vGI72NUBoRH/view):
read_excel("E:/storytelling/3.1 EXERCISE.xlsx", skip = 0) %>%
select(-c(1, 2)) -> rawData_3.1
rawData_3.1 %>%
slice(7) %>%
as.vector() %>%
as.numeric() -> sales
c(rep(2018, 12), rep(2019, 12)) -> year
c(rep("ACTUAL", 17), rep("FORECAST", 7)) -> type
monthLabels <- rep(month.abb, each = 1, time = 2)
monthLabels[1] <- "Jan\n2018"
monthLabels[13] <- "Jan\n2019"
# Create data:
data.frame(sales = sales,
year = year,
type = type,
month = monthLabels,
myTime = 1:24) -> dataLong
leftText <- "**2018:** Jan-Jun was a period of stability, with\nfairly steady growth (averaging +3% per\nmonth). There was a <span style = 'color:#ff7f00'>**nearly 20% decrease\nin July**</span>, when Product X was recalled and\npulled from the market. Total sales remained\nat reduced volume for the rest of the year."
rightText <- "**2019:** The year started at less than $1.6B, but\n<span style = 'color:#377eb8'>**increased markedly in February**</span>, when a new\nstudy was released. Total sales have increased\nsteadily since then and this is projected to continue.\nThe latest forecast is for $2.4B in monthly sales by the end of the year.
"
textAddted <- "**2019 FORECAST**\nThis is provided\nby ABC consultants and based on market data through June. The forecast assumes no major market changes."
dfText <- data.frame(myTime = 1, rightText = rightText, leftText = leftText, textAddted = textAddted)
dataLong %>%
filter(myTime %in% c(1, 6, 7, 14, 18, 24)) %>%
mutate(labelDollar = round(sales, 1)) %>%
mutate(labelDollar = paste0("$", labelDollar, "B")) %>%
mutate(labelDollar = case_when(myTime == 18 ~ "$2.0B",
TRUE ~ labelDollar)) -> textLabelDollar
library(ggplot2)
library(scales)
library(ggtext)
library(showtext)
# my_font <- "Poppins"
my_font <- "Open Sans"
font_add_google(name = my_font, family = my_font)
showtext_auto()
colorBar <- c("#ff7f00", "#377eb8")
dataLong %>%
ggplot(aes(x = myTime, y = sales)) +
geom_rect(aes(xmin = 18, xmax = 24, ymin = -Inf, ymax = 2.5), fill = "grey90") +
theme_minimal() +
theme(text = element_text(family = my_font)) +
theme(plot.title.position = "plot") +
geom_line(data = dataLong %>% filter(myTime >= 18), linetype = "dashed",
size = 1, color = "grey30") +
geom_line(data = dataLong %>% filter(myTime <= 18), size = 1.2, color = "grey30") +
geom_point(data = dataLong %>% filter(year == 2018, month %in% c("Jan", "Jun")),
size = 4, color = "grey30") +
geom_point(data = dataLong %>% filter(year == 2018, month %in% c("Jul")),
color = "grey30", size = 4, shape = 21, fill = "#ff7f00") +
geom_point(data = dataLong %>% filter(year == 2019, month %in% c("Feb")),
color = "grey30", size = 4, shape = 21, fill = "#377eb8") +
geom_point(data = dataLong %>% filter(year == 2019, month %in% c("Jun")),
color = "grey30", size = 4) +
geom_point(data = dataLong %>% filter(year == 2019, month %in% c("Dec")),
color = "grey30", size = 4, shape = 21, fill = "white") +
scale_y_continuous(limits = c(0, 3.5), breaks = seq(0, 3.5, 0.5),
labels = dollar, expand = c(0, 0)) +
scale_x_continuous(limits = c(0.3, 24.8), breaks = 1:24,
labels = monthLabels, expand = c(0, 0)) +
geom_textbox(
data = dfText,
aes(x = myTime, y = 3.5, label = leftText, box.color = NA),
width = 0.4,
hjust = 0,
vjust = 1,
fill = NA,
color = "grey40",
family = my_font,
size = 3.5
) +
geom_textbox(
data = dfText,
aes(x = myTime + 12, y = 3.5, label = rightText, box.color = NA),
width = 0.4,
hjust = 0,
vjust = 1,
fill = NA,
color = "grey40",
family = my_font,
size = 3.5
) +
theme(axis.text.x = element_text(hjust = 0, size = 10)) +
theme(axis.text.y = element_text(hjust = 0, size = 11)) +
labs(title = "Market Size over Time",
caption = "Source: https://www.storytellingwithdata.com/") +
theme(axis.title = element_blank()) +
theme(plot.margin = margin(0.7, 0.5, 0.5, 0.7, "cm")) +
theme(plot.caption = element_text(color = "grey40")) +
theme(plot.title = element_text(size = 18, color = "grey20", vjust = 3)) +
theme(panel.grid = element_blank()) -> plotDraft
plotDraft +
geom_text(data = textLabelDollar %>% filter(myTime != 7), aes(label = labelDollar),
vjust = -1, family = my_font, size = 4, color = "grey30") +
geom_text(data = textLabelDollar %>% filter(myTime == 7), aes(label = labelDollar),
vjust = 1.8, family = my_font, size = 4, color = "grey30")