Reputation: 2587
I'm following along with the example on page 82 from ggplot2 by Hadley Wickham.
presidential <- presidential[-(1:3), ]
yrng <- range(economics$unemploy)
xrng <- range(economics$date)
unemp + geom_vline(aes(xintercept = start), data = presidential
unemp + geom_rect(aes(NULL, NULL, xmin = start, xmax = end,
fill = party), ymin = yrng[1], ymax = yrng[2],
data = presidential) + scale_fill_manual(values =
alpha(c("blue", "red"), 0.2))
That's the code that is used in the book to generate a plot with shaded backgrounds.
I'd like to do the same thing, except with the data from the Tour de France
Here's my code.
library(tidyverse)
library(lubridate)
# organize the data
tdf_winners <- read_csv('https://raw.githubusercontent.com/rfordatascience/tidytuesday/master/data/2020/2020-04-07/tdf_winners.csv')
wins.by.winner_name <-
tdf_winners %>%
count(winner_name) %>%
arrange(-n) %>%
mutate(total_wins = n) %>%
select(-n)
tdf_winners <-
tdf_winners %>%
filter(start_date > ymd("1913-01-01")) %>%
left_join(wins.by.winner_name, by = "winner_name") %>%
mutate(winner_name_lbl = ifelse(total_wins == 1, "One Time Winner",
winner_name))
# create the graphic
yrng <- range(tdf_winners$time_overall[!is.na(tdf_winners$time_overall)])
xrng <- range(tdf_winners$edition)
tdf_winners %>%
ggplot(aes(edition, time_overall)) +
geom_col() +
geom_rect(aes(NULL, NULL,
xmin = edition, xmax = edition, fill = winner_name_lbl),
ymin = yrng[1], ymax = yrng[2],
data = tdf_winners) +
scale_fill_manual(values = alpha(c("blue", "red",
"green", "purple",
"pink", "orange",
"yellow", "violet",
"black", "maroon",
"lightblue", "lightgreen",
"lightpink", "navy",
"lightyellow", "royalblue",
"grey", "lightgrey",
"darkgrey", "darkgreen", "white"
)))
Unfortunately, it doesn't create the shaded background. I'd like to have a shade that depends on the winner name.
How do I create this?
Upvotes: 1
Views: 913
Reputation: 93761
I think geom_tile
is easier to work with here. It's similar to geom_rect
, but the rectangles are parametrized by their center, height, and width, rather than the locations of the four vertices.
my_colors = c("blue", "red",
"green", "purple",
"pink", "orange",
"yellow", "violet",
"black", "maroon",
"lightblue", "lightgreen",
"lightpink", "navy",
"lightyellow", "royalblue",
"grey", "lightgrey",
"darkgrey", "darkgreen", "white")
tdf_winners %>%
ggplot(aes(edition, time_overall)) +
geom_tile(aes(x=edition, y=125, width=1, height=250, fill = winner_name_lbl), alpha=0.4) +
geom_col(fill="grey50") +
scale_fill_manual(values = my_colors) +
scale_y_continuous(limits=c(0, 250), expand=c(0,0)) +
theme_classic()
Here's another option that I think is easier on the eyes:
winners = tdf_winners %>%
arrange(edition) %>%
mutate(winner.change = cumsum(c(0, diff(as.numeric(factor(winner_name))))!=0)) %>%
group_by(winner.change) %>%
summarise(edition.ctr = mean(edition),
width = n(),
winner_name = unique(winner_name)) %>%
ungroup() %>%
mutate(winner.change = factor(winner.change %% 2))
tdf_winners %>%
ggplot(aes(edition, time_overall)) +
geom_tile(data=winners, colour="white", show.legend=FALSE,
aes(x=edition.ctr, y=125, width=width, height=250, fill=winner.change), alpha=0.4) +
geom_line(colour="grey50") +
geom_point(colour="grey20") +
scale_fill_manual(values = hcl(c(15,195), 100, 80)) +
scale_y_continuous(limits=c(0, 250), expand=c(0,0)) +
scale_x_continuous(breaks=winners$edition.ctr, labels=winners$winner_name,
expand=expansion(c(0.01,.01)),
sec.axis=sec_axis(~ .,
breaks=tdf_winners$edition,
labels=year(tdf_winners$start_date))) +
theme_classic() +
theme(axis.text.x=element_text(angle=-90, vjust=0.5, hjust=0),
axis.text.x.top=element_text(angle=-90, hjust=0.5, vjust=0.5, size=8)) +
labs(x="", y="Time")
Zooming in to get a better look at a portion of the plot:
A couple of other notes:
geom_rect
wasn't doing anything in your example, because xmin = edition, xmax = edition
results in a rectangle of zero width.
The alpha()
function isn't necessary unless you want to set a transparency value for the fill colors.
Upvotes: 3