A bump chart is a type of chart that shows rankings of different groups over time instead of absolute values to emphasize the order of the groups instead of the magnitude of change.
This tutorial explains how to easily create a bump chart in R using ggplot2.
Example: Creating a Bump Chart
To create a bump chart in R, we first need to load two packages: dplyr and ggplot2:
library(ggplot2) #for creating bump chart library(dplyr) #for manipulating data
Next, we’ll create some data to work with:
#set the seed to make this example reproducible
set.seed(10)
data %
group_by(day) %>%
arrange(day, desc(random_num), team) %>%
mutate(rank = row_number()) %>%
ungroup()
head(data)
# team random_num day rank
#1 C 0.865 1 1
#2 B 0.652 1 2
#3 D 0.536 1 3
#4 A 0.507 1 4
#5 E 0.275 1 5
#6 C 0.615 2 1
This data frame simply shows the “rank” of five different teams across a time span of 10 days.
We can use ggplot2 to create a bump chart to visualize the rank of each team during each day over this time span:
ggplot(data, aes(x = day, y = rank, group = team)) + geom_line(aes(color = team, alpha = 1), size = 2) + geom_point(aes(color = team, alpha = 1), size = 4) + scale_y_reverse(breaks = 1:nrow(data))
This bump chart shows the data in the format that we want, but it’s fairly ugly. With some aesthetic changes, we can make this chart look much better.
Styling the Bump Chart
To make the chart look better, we can use the following theme created by Dominik Koch:
my_theme
We’ll create the bump chart again, but this time we’ll remove the legend, add some chart labels, and use the theme defined in the code above:
ggplot(data, aes(x = as.factor(day), y = rank, group = team)) + geom_line(aes(color = team, alpha = 1), size = 2) + geom_point(aes(color = team, alpha = 1), size = 4) + geom_point(color = "#FFFFFF", size = 1) + scale_y_reverse(breaks = 1:nrow(data)) + scale_x_discrete(breaks = 1:10) + theme(legend.position = 'none') + geom_text(data = data %>% filter(day == "1"), aes(label = team, x = 0.5) , hjust = .5, fontface = "bold", color = "#888888", size = 4) + geom_text(data = data %>% filter(day == "10"), aes(label = team, x = 10.5) , hjust = 0.5, fontface = "bold", color = "#888888", size = 4) + labs(x = 'Day', y = 'Rank', title = 'Team Ranking by Day') + my_theme()
We can also easily highlight one of the lines by adding a scale_color_manual() argument. For example, in the following code we make the line for team A purple and the line for all of the other lines grey:
ggplot(data, aes(x = as.factor(day), y = rank, group = team)) +
geom_line(aes(color = team, alpha = 1), size = 2) +
geom_point(aes(color = team, alpha = 1), size = 4) +
geom_point(color = "#FFFFFF", size = 1) +
scale_y_reverse(breaks = 1:nrow(data)) +
scale_x_discrete(breaks = 1:10) +
theme(legend.position = 'none') +
geom_text(data = data %>% filter(day == "1"),
aes(label = team, x = 0.5) , hjust = .5,
fontface = "bold", color = "#888888", size = 4) +
geom_text(data = data %>% filter(day == "10"),
aes(label = team, x = 10.5) , hjust = 0.5,
fontface = "bold", color = "#888888", size = 4) +
labs(x = 'Day', y = 'Rank', title = 'Team Ranking by Day') +
my_theme() +
scale_color_manual(values = c('purple', 'grey', 'grey', 'grey', 'grey'))
We could also highlight more than one line if we’d like:
ggplot(data, aes(x = as.factor(day), y = rank, group = team)) +
geom_line(aes(color = team, alpha = 1), size = 2) +
geom_point(aes(color = team, alpha = 1), size = 4) +
geom_point(color = "#FFFFFF", size = 1) +
scale_y_reverse(breaks = 1:nrow(data)) +
scale_x_discrete(breaks = 1:10) +
theme(legend.position = 'none') +
geom_text(data = data %>% filter(day == "1"),
aes(label = team, x = 0.5) , hjust = .5,
fontface = "bold", color = "#888888", size = 4) +
geom_text(data = data %>% filter(day == "10"),
aes(label = team, x = 10.5) , hjust = 0.5,
fontface = "bold", color = "#888888", size = 4) +
labs(x = 'Day', y = 'Rank', title = 'Team Ranking by Day') +
my_theme() +
scale_color_manual(values = c('purple', 'steelblue', 'grey', 'grey', 'grey'))