Explanatory visuals, part 3: Ways to direct attention
- sam33frodon
- Aug 25, 2021
- 12 min read
Updated: Aug 31, 2021
Note: All of the following graphs were created using ggplot2 and are inspired from the book Storytelling With Data: Let’s Practice!
(Ref: Knaflic, Cole. Storytelling With Data: Let’s Practice! Wiley, © 2019.)
The author created all the figures using Excel and PowerPoint.
In this post, I will use mainly two ubiquitous packages, namely ggplot2 (for data visualization) and tidyverse (for data transforming).
Case study 1. Conversion rate over time by acquisition channel
Data preparation code for case study 1 (R code)
1.1. Basic chart

Figure 1. Basic chart (R code)
1.2. Thicken the line

Figure 2. Thicken the line (R code)
1.3. Change the line style

Figure 3. Change the line style (R code)
1.4. Leverage intensity

Figure 4. Make it darker (R code)
1.5. Position in front of other data

Figure 5. Position in front of other data (R code)
1.6. Change the hue

Figure 6. Change the hue (R code)
1.7. Use words to prime audience

Figure 7. Use title words to prime audience (R code)
1.8. Eliminate the other data

Figure 8. Eliminate the other data (R code)
1.9. Add data markers

Figure 9. Add data markers (R code)
1.10. Add data labels

Figure 10. Add data labels (R code)
1.11. Employ end markers and labels

Figure 11. Employ end markers and labels (R code)
1.12. Combine multiple pre-attentive attributes

Figure 12. Combine multiple pre-attentive attributes (R code)
Case study 2
The scenario: We work at Financial Savings and want to compare your bank’s performance against your peers’. We have data on bank index (branch satisfaction) over time for your bank plus a number of your competitors.
Data preparation (R code)

Figure 13. Can show all the data if we push most of it to the background (R code)

Figure 14. Could focus on latest year-to-year period of time (R code)
Coding
Data preparation
year <- c(2005:2019)
total <- c(8.7,8.3,8.6,8.9,8.4,8.6,7.5,7.2,6.9,7.4,6.6,8.0,7.3,7.0,6.3)
organic <- c(3.3,3.5,3.7, 3.6, 3.4, 3.1, 3.2,3.5, 3.2, 3.8, 3.5, 4.5, 4.1, 4.2,3.8)
referral <- c(5.4,4.8,4.9,5.3,5.0,5.5,4.3,3.7,3.7,3.6,3.1,3.5,3.2,2.8,2.5)
df_wide <- tibble(year, organic, referral, total)
df_wide
## # A tibble: 15 x 4
## year organic referral total
## <int> <dbl> <dbl> <dbl>
## 1 2005 3.3 5.4 8.7
## 2 2006 3.5 4.8 8.3
## 3 2007 3.7 4.9 8.6
## 4 2008 3.6 5.3 8.9
## 5 2009 3.4 5 8.4
## 6 2010 3.1 5.5 8.6
## 7 2011 3.2 4.3 7.5
## 8 2012 3.5 3.7 7.2
## 9 2013 3.2 3.7 6.9
## 10 2014 3.8 3.6 7.4
## 11 2015 3.5 3.1 6.6
## 12 2016 4.5 3.5 8
## 13 2017 4.1 3.2 7.3
## 14 2018 4.2 2.8 7
## 15 2019 3.8 2.5 6.3
df_long <- df_wide %>%
pivot_longer(cols = c("organic","referral","total"),
names_to = "type",
values_to = "value")
head(df_long,10)
## # A tibble: 10 x 3
## year type value
## <int> <chr> <dbl>
## 1 2005 organic 3.3
## 2 2005 referral 5.4
## 3 2005 total 8.7
## 4 2006 organic 3.5
## 5 2006 referral 4.8
## 6 2006 total 8.3
## 7 2007 organic 3.7
## 8 2007 referral 4.9
## 9 2007 total 8.6
## 10 2008 organic 3.6
Code for figure 1
theme_attention <- theme(plot.title = element_text(size = 20, vjust = 6, hjust = -0.15),
axis.text.x = element_text(size=12, color = "#6d6d6d"),
axis.text.y = element_text(size=12, color = "#6d6d6d",hjust = 0.1),
axis.title.x= element_text(size = 12, hjust = 0, vjust = -4, color = "#6d6d6d"),
axis.title.y = element_text(size = 12, hjust = 1 ,vjust = 4, color = "#6d6d6d"),
axis.line.x= element_line(color="#a9a9a9"),
axis.line.y= element_line(color="#a9a9a9", size = 1),
axis.ticks = element_line(color="#a9a9a9") ,
legend.position = "none",
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
panel.background = element_blank(),
plot.margin = unit(c(1,2.75,1,1),"cm"))
ggplot(data= df_long,
aes(x= year, y = value, group = type))+
geom_line(color = "#6d6d6d", size = 1.5) +
annotate("text", x = 2019.2, y = 3.8, label = "ORGANIC", color = "#6d6d6d", hjust = 0, size = 4.5) +
annotate("text", x = 2019.2, y = 2.5, label = "REFERRAL", color ="#6d6d6d", hjust = 0, size = 4.5) +
annotate("text", x = 2019.2, y = 6.3, label = "TOTAL", color = "#6d6d6d", hjust = 0, size = 4.5) +
scale_x_continuous(expand = c(0, 0),n.breaks = 14) +
coord_cartesian(xlim = c(2005, 2019), clip = 'off') +
scale_y_continuous(expand = c(0, 0),limits = c(0, 10), n.breaks = 10) +
labs(title = "Conversion rate over time",
y = "CONVERSION RATE (%)",
x = "FISCAL YEAR") +
theme_attention
Code for figure 2
ggplot(data= df_long,
aes(x= year, y = value, group = type))+
geom_line(color = "#a9a9a9", size = 1.) +
geom_line(data = filter(df_long, type == "referral") , color = "#a9a9a9", size = 2) +
annotate("text", x = 2019.2, y = 3.8, label = "ORGANIC", color = "#a9a9a9", hjust = 0, size = 4.5) +
annotate("text", x = 2019.2, y = 2.5, label = "REFERRAL", color ="#6d6d6d", hjust = 0, size = 4.5, fontface="bold") +
annotate("text", x = 2019.2, y = 6.3, label = "TOTAL", color = "#a9a9a9", hjust = 0, size = 4.5) +
scale_x_continuous(expand = c(0, 0),n.breaks = 14) +
coord_cartesian(xlim = c(2005, 2019), clip = 'off') +
scale_y_continuous(expand = c(0, 0),limits = c(0, 10), n.breaks = 10) +
labs(title = "Coversion rate over time",
x = "FISCAL YEAR",
y = "CONVERSION RATE (%)") +
theme_attention
Code for figure 3
ggplot(data= df_long,
aes(x= year, y = value, group = type))+
geom_line(data = filter(df_long, type == "referral"), color = "#a9a9a9", size = 1.5, linetype = "dashed") +
geom_line(data = filter(df_long, type == "organic" | type == "total"), color = "#a9a9a9", size = 1.5) +
annotate("text", x = 2019.2, y = 3.8, label = "ORGANIC", color = "#a9a9a9", hjust = 0, size = 4.5) +
annotate("text", x = 2019.2, y = 2.5, label = "REFERRAL", color ="#a9a9a9", hjust = 0, size = 4.5) +
annotate("text", x = 2019.2, y = 6.3, label = "TOTAL", color = "#a9a9a9", hjust = 0, size = 4.5) +
scale_x_continuous(expand = c(0, 0),n.breaks = 14) +
coord_cartesian(xlim = c(2005, 2019), clip = 'off') +
scale_y_continuous(expand = c(0, 0),limits = c(0, 10), n.breaks = 10) +
labs(title = "Coversion rate over time",
x = "FISCAL YEAR",
y = "CONVERSION RATE (%)") +
theme_attention
Code for figure 4
ggplot(data= df_long,
aes(x= year, y = value, group = type))+
geom_line(data = filter(df_long, type == "referral"), color = "black", size = 1.5) +
geom_line(data = filter(df_long, type == "organic" | type == "total"), color = "#a9a9a9", size = 1.5) +
annotate("text", x = 2019.2, y = 2.5, label = "REFERRAL", color ="black", hjust = 0, size = 4.5) +
annotate("text", x = 2019.2, y = 3.8, label = "ORGANIC", color = "#a9a9a9", hjust = 0, size = 4.5) +
annotate("text", x = 2019.2, y = 6.3, label = "TOTAL", color = "#a9a9a9", hjust = 0, size = 4.5) +
scale_x_continuous(expand = c(0, 0),n.breaks = 14) +
coord_cartesian(xlim = c(2005, 2019), clip = 'off') +
scale_y_continuous(expand = c(0, 0),limits = c(0, 10), n.breaks = 10) +
labs(title = "Coversion rate over time",
x = "FISCAL YEAR",
y = "CONVERSION RATE (%)") +
theme_attention
Code for figure 5
ggplot(data= df_long,
aes(x= year, y = value, group = type))+
geom_line(data = filter(df_long, type == "organic" | type == "total"), color = "#a9a9a9", size = 1.5) +
geom_line(data = filter(df_long, type == "referral"), color = "black", size = 1.5) + # putting the line in front
annotate("text", x = 2019.2, y = 2.5, label = "REFERRAL", color ="black", hjust = 0, size = 4.5) +
annotate("text", x = 2019.2, y = 3.8, label = "ORGANIC", color = "#a9a9a9", hjust = 0, size = 4.5) +
annotate("text", x = 2019.2, y = 6.3, label = "TOTAL", color = "#a9a9a9", hjust = 0, size = 4.5) +
scale_x_continuous(expand = c(0, 0),n.breaks = 14) +
coord_cartesian(xlim = c(2005, 2019), clip = 'off') +
scale_y_continuous(expand = c(0, 0),limits = c(0, 10), n.breaks = 10) +
labs(title = "Coversion rate over time",
x = "FISCAL YEAR",
y = "CONVERSION RATE (%)") +
theme_attention
Code for figure 6
ggplot(data= df_long,
aes(x= year, y = value, group = type))+
geom_line(data = filter(df_long, type == "organic" | type == "total"), color = "#a9a9a9", size = 1.5) +
geom_line(data = filter(df_long, type == "referral"), color = "#FF0000", size = 1.5) + # putting the line in front
annotate("text", x = 2019.2, y = 2.5, label = "REFERRAL", color = "#FF0000", hjust = 0, size = 4.5) +
annotate("text", x = 2019.2, y = 3.8, label = "ORGANIC", color = "#a9a9a9", hjust = 0, size = 4.5) +
annotate("text", x = 2019.2, y = 6.3, label = "TOTAL", color = "#a9a9a9", hjust = 0, size = 4.5) +
scale_x_continuous(expand = c(0, 0),n.breaks = 14) +
coord_cartesian(xlim = c(2005, 2019), clip = 'off') +
scale_y_continuous(expand = c(0, 0),limits = c(0, 10), n.breaks = 10) +
labs(title = "Coversion rate over time",
x = "FISCAL YEAR",
y = "CONVERSION RATE (%)") +
theme_attention
Code for figure 7
ggplot(data= df_long,
aes(x= year, y = value, group = type))+
geom_line(color = "#a9a9a9", size = 2) +
annotate("text", x = 2019.2, y = 3.8, hjust = 0,
label = "ORGANIC", color = "#a9a9a9", size = 4.5, fontface = "bold") +
annotate("text", x = 2019.2, y = 2.5, hjust = 0,
label = "REFERRAL", color ="#a9a9a9", size = 4.5, fontface = "bold") +
annotate("text", x = 2019.2, y = 6.3, hjust = 0,
label = "TOTAL", color = "#a9a9a9", size = 4.5, fontface = "bold") +
scale_x_continuous(expand = c(0, 0),n.breaks = 14) +
coord_cartesian(xlim = c(2005, 2019), clip = 'off') +
scale_y_continuous(expand = c(0, 0),limits = c(0, 10), n.breaks = 10) +
labs(title = "Conversion rate over time: Referral decreasing markedly since 2010",
x = "FISCAL YEAR",
y = "CONVERSION RATE (%)") +
theme(plot.title = element_text(size = 20, vjust = 6, hjust = 0.5),
axis.text.x = element_text(size=12, color = "#a9a9a9"),
axis.text.y = element_text(size=12, color = "#a9a9a9",hjust = 0.1),
axis.title.x= element_text(size = 12, hjust = 0, vjust = -4, color = "#a9a9a9"),
axis.title.y = element_text(size = 12, hjust = 1 ,vjust = 4, color = "#a9a9a9"),
axis.line.x= element_line(color="#a9a9a9"),
axis.line.y= element_line(color="#a9a9a9", size = 1),
axis.ticks = element_line(color="#a9a9a9"),
legend.position = "none",
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
panel.background = element_blank(),
plot.margin = unit(c(1,2.75,1,1),"cm"))
Code for figure 8
ggplot(data = filter(df_long, type == "referral"),
aes(x= year, y = value, group = type))+
# geom_line(color = "#a9a9a9", size = 2) +
geom_line(color = "#a9a9a9", size = 2) +
#annotate("text", x = 2019.2, y = 3.8, label = "ORGANIC", color = "#a9a9a9", hjust = 0, size = 4.5, fontface = "bold") +
annotate("text", x = 2019.2, y = 2.5, label = "REFERRAL", color ="#a9a9a9", hjust = 0, size = 4.5, fontface = "bold") +
#annotate("text", x = 2019.2, y = 6.3, label = "TOTAL", color = "#a9a9a9", hjust = 0, size = 4.5, fontface = "bold") +
scale_x_continuous(expand = c(0, 0),n.breaks = 14) +
coord_cartesian(xlim = c(2005, 2019), clip = 'off') +
scale_y_continuous(expand = c(0, 0),limits = c(0, 10), n.breaks = 10) +
labs(title = "Coversion rate over time",
x = "FISCAL YEAR",
y = "CONVERSION RATE (%)") +
theme_attention
Code for figure 9
ggplot(data= df_long,
aes(x= year, y = value, group = type))+
geom_line(color = "#a9a9a9", size = 1.75) +
geom_point(data = filter(df_long, type == "referral") , color = "#a9a9a9", size = 4.25) +
annotate("text", x = 2019.2, y = 3.8, label = "ORGANIC", color = "#a9a9a9", hjust = 0, size = 4.5, fontface = "bold") +
annotate("text", x = 2019.2, y = 2.5, label = "REFERRAL", color ="#a9a9a9", hjust = 0, size = 4.5, fontface = "bold") +
annotate("text", x = 2019.2, y = 6.3, label = "TOTAL", color = "#a9a9a9", hjust = 0, size = 4.5, fontface = "bold") +
scale_x_continuous(expand = c(0, 0),n.breaks = 14) +
coord_cartesian(xlim = c(2005, 2019), clip = 'off') +
scale_y_continuous(expand = c(0, 0),limits = c(0, 10), n.breaks = 10) +
labs(title = "Coversion rate over time",
x = "FISCAL YEAR",
y = "CONVERSION RATE (%)") +
theme_attention
Code for figure 10
ggplot(data= df_long,
aes(x= year, y = value, group = type))+
geom_line(color = "#a9a9a9", size = 2) +
geom_point(data = filter(df_long, type == "referral") , color = "#a9a9a9", size = 4) +
geom_text(data = filter(df_long, type == "referral"),
aes(label = paste(format(value), "%", sep = "")),
size = 4.5, color = "#a9a9a9", vjust = -1) +
annotate("text", x = 2019.2, y = 3.8, label = "ORGANIC", color = "#a9a9a9", hjust = 0, size = 4.5, fontface = "bold") +
annotate("text", x = 2019.2, y = 2.5, label = "REFERRAL", color ="#a9a9a9", hjust = 0, size = 4.5, fontface = "bold") +
annotate("text", x = 2019.2, y = 6.3, label = "TOTAL", color = "#a9a9a9", hjust = 0, size = 4.5, fontface = "bold") +
scale_x_continuous(expand = c(0, 0),n.breaks = 14) +
coord_cartesian(xlim = c(2005, 2019), clip = 'off') +
scale_y_continuous(expand = c(0, 0),limits = c(0, 10), n.breaks = 5) +
labs(title = "Coversion rate over time",
x = "FISCAL YEAR",
y = "CONVERSION RATE (%)") +
theme_attention
Code for figure 11
ggplot(data= df_long,
aes(x= year, y = value, group = type))+
geom_line(color = "#a9a9a9", size = 2) +
annotate("text", x = 2019.2, y = 3.8, label = "3.8% ORGANIC", color = "#a9a9a9", hjust = 0, size = 4.5, fontface = "bold") +
annotate("text", x = 2019.2, y = 2.5, label = "2.5% REFERRAL", color ="#a9a9a9", hjust = 0, size = 4.5, fontface = "bold") +
annotate("text", x = 2019.2, y = 6.3, label = "6.3% TOTAL", color = "#a9a9a9", hjust = 0, size = 4.5, fontface = "bold") +
scale_x_continuous(expand = c(0, 0),n.breaks = 14) +
coord_cartesian(xlim = c(2005, 2019), clip = 'off') +
scale_y_continuous(expand = c(0, 0),limits = c(0, 10), n.breaks = 5) +
labs(title = "Coversion rate over time",
x = "FISCAL YEAR",
y = "CONVERSION RATE (%)") +
theme_attention +
theme(plot.margin = unit(c(1,4,1,1),"cm"))
Code for figure 12
ggplot(data= df_long,
aes(x= year, y = value, group = type))+
geom_line(color = "#a9a9a9", size = 2) +
geom_line(data = filter(df_long, type == "referral"), color = "#FF0000", size = 1.5) + # putting the line in front
geom_point(data = filter(df_long, type == "referral", year %in% c(2010, 2016, 2019)), color = "#FF0000", size = 5) +
annotate("text", x = 2019.3, y = 3.8, label = "3.8% ORGANIC", color = "#a9a9a9", hjust = 0, size = 4.5, fontface = "bold") +
annotate("text", x = 2019.3, y = 2.5, label = "2.5% REFERRAL", color = "#FF0000", hjust = 0, size = 4.5, fontface = "bold") +
annotate("text", x = 2019.3, y = 6.3, label = "6.3% TOTAL", color = "#a9a9a9", hjust = 0, size = 4.5, fontface = "bold") +
scale_x_continuous(expand = c(0, 0),n.breaks = 14) +
coord_cartesian(xlim = c(2005, 2019), clip = 'off') +
scale_y_continuous(expand = c(0, 0),limits = c(0, 10), n.breaks = 5) +
labs(title = "Coversion rate over time: <span style = 'color:#FF0000;'>**referral decreasing markedly since 2010**</span>",
x = "FISCAL YEAR",
y = "CONVERSION RATE (%)") +
theme(plot.title = element_markdown(size = 18, hjust = 0.625),
axis.text.x = element_text(size=12, color = "#a9a9a9"),
axis.text.y = element_text(size=12, color = "#a9a9a9",hjust = 0.1),
axis.title.x= element_text(size = 12, hjust = 0, vjust = -4, color = "#a9a9a9"),
axis.title.y = element_text(size = 12, hjust = 1 ,vjust = 4, color = "#a9a9a9"),
axis.line.x= element_line(color="#a9a9a9"),
axis.line.y= element_line(color="#a9a9a9", size = 1),
legend.position = "none",
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
panel.background = element_blank(),
plot.margin = unit(c(0.5,4,1,1),"cm"))
Data preparation code for case study 2
data_w <- read_csv("bank.csv")
data_l <- data_w%>%
pivot_longer(cols = c("2012","2013","2014","2015","2016","2017","2017","2018","2019"),
names_to = "year",
values_to = "score")
data_l$year <- as.numeric(data_l$year)
Code for figure 13
ggplot(data = data_l,
aes(x= year, y = score, group=bank))+
geom_line(size = 1.5, color = "#a9a9a9") +
geom_line(data = filter(data_l, bank == "Industry Average"), size = 1.5, color = "black") +
geom_line(data = filter(data_l, bank == "Financial Savings"), size = 1.5, color = "#4169e1") +
geom_point(data = filter(data_l, bank == "Industry Average", year == 2019), size = 4, color = "black") +
geom_point(data = filter(data_l, bank == "Financial Savings", year == 2019), size = 4, color = "#4169e1") +
annotate("text", x = 2020, y = 850, label = "Industry Average", color = "black", size = 5) +
annotate("text", x = 2020, y = 837.5, label = "Financial Savings", color = "#4169e1", size = 5) +
scale_x_continuous(expand = c(0, 0),n.breaks = 10) +
coord_cartesian(xlim = c(2012, 2019), clip = 'off') +
scale_y_continuous(expand = c(0, 0),limits = c(700, 900), n.breaks = 10) +
labs(title = "BRANCH SATISFACTION<br><span style = 'color:#4169e1;'>**Financial Savings**</span> below <span style ='color:#000000;'>**industry**</span> for the first 5 years") +
ylab("SATISFACTION SCORE") +
xlab("SURVEY YEAR") +
theme(plot.title = element_markdown(size = 20, lineheight = 1.25),
plot.title.position = "plot",
axis.text.x = element_text(size=12, vjust = -2) ,
axis.text.y = element_text(size=12, hjust = -3),
axis.title.x= element_text(size = 12, hjust = 0, vjust = -2.5, color ="black"),
axis.title.y = element_text(size = 12, hjust = 1, vjust = 2.5 , color ="black"),
axis.line.x= element_line(color="grey"),
axis.line.y= element_line(color="grey", size = 1),
axis.ticks = element_line(color="#a9a9a9"),
legend.position = "none",
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
panel.background = element_blank(),
plot.margin=unit(c(0.5,4.5,1,1),"cm"))
Code for figure 14
df <- tibble(label =
"<span style='color:#4169e1'>**Financial Savings increased 1%**</span>
in satisfaction score in the past year, whereas
<span style='color:#000000'>**the industry increased an average of 3%**</span>
<span style ='color:#93C572'>(1-5% each)</span>",
x = 2018, y = 760, color ="white", contourfill = "white")
ggplot(data = data_l,
aes(x= year, y = score))+
geom_line(aes(group = bank), size = 1.25, color = "#a9a9a9") +
geom_line(data = filter(data_l, year == 2018 | year == 2019), aes(group = bank), size = 1.25, color = "#93C572") +
geom_line(data = filter(data_l, bank == "Industry Average"), size = 1.5, color = "black") +
geom_line(data = filter(data_l, bank == "Financial Savings"),size = 1.5, color = "#4169e1") +
geom_point(data = filter(data_l, bank == "Industry Average", year == 2019), size = 4, color = "black") +
geom_point(data = filter(data_l, bank == "Financial Savings", year == 2019), size = 4, color = "#4169e1") +
geom_textbox(data = df, aes(x,y, label = label),size= 4.5, box.color = "white",
fill = "white", hjust = 0, vjust = 0.9,
halign = 1,
width = unit(160, "pt"),
box.padding = unit(c(0, 0, 0, 0), "pt")) +
annotate("text", x = 2020, y = 850, label = "Industry Average", color = "black", size = 5) +
annotate("text", x = 2020, y = 837.5, label = "Financial Savings", color = "#4169e1", size = 5) +
scale_x_continuous(expand = c(0, 0),n.breaks = 10) +
coord_cartesian(xlim = c(2012, 2019), clip = 'off') +
scale_y_continuous(expand = c(0, 0),limits = c(700, 900), n.breaks = 10) +
labs(title = "BRANCH SATISFACTION<br><span style = 'color:#4169e1;'>**Financial Savings**</span> below <span style ='color:#000000;'>**industry**</span> for the first 5 years") +
ylab("SATISFACTION SCORE") +
xlab("SURVEY YEAR") +
theme(plot.title = element_markdown(size = 18, lineheight = 1.25),
plot.title.position = "plot",
axis.text.x = element_text(size=12, vjust = -2) ,
axis.text.y = element_text(size=12, hjust = -3),
axis.title.x= element_text(size = 12, hjust = 0, vjust = -2.5, color ="black"),
axis.title.y = element_text(size = 12, hjust = 1, vjust = 2.5 , color ="black"),
axis.line.x= element_line(color="grey"),
axis.line.y= element_line(color="grey", size = 1),
axis.ticks = element_line(color="#a9a9a9"),
legend.position = "none",
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
panel.background = element_blank(),
plot.margin=unit(c(0.5,4.5,1,1),"cm"))
-------- END------
Comments