I want to create a Gannt chart for a 3 year period, with the seasons lightly shaded, i.e., displayed as rectangles in background. The Y values are 'tasks' and I do not know how to get these character data accepted for the ymin and ymax arguments of geom_area(). It would also be great to know how to make a legend for the shading, and how to make it transparent. Here's what I have:
# make a data frame with timing of activities
act <- data.frame(
task = c('Site preparation', 'Seed collection'),
start=c('01/01/2026', '11/1/2026'),
end = c('02/01/2026','12/15/2027'),
group=c('TT-Livingston staff','TT-Pyrosilviculture'))
# Format start and end dates as Dates
act$start = with(act, as.Date(start, format = '%m/%d/%Y'))
act$end = with(act, as.Date(end, format = '%m/%d/%Y'))
#activ <- c(
# "Site preparation",
# "Seed collection",
#---------- Change tasks to ordered factors--
act$task <- with(act, factor(task, levels = rev(activ), ordered=TRUE))
#------- Create a data frame with information for background shading -----
st <- as.Date("2025-12-01") # Start date
en <- as.Date("2028-09-01") # End date
rect_L <- seq(st + 1, en + 1, by = "3 months") - 1 #Left side of rectangle
rect_R <- seq(st + 31, en + 31 , by = "3 months") - 1 # Right sides of rectangles
season <- rep(c("winter","spring","summer","autumn"),3)
shades <- rep(c("grey70","green","yellow","pink"),3)
shade <- data.frame(
xmin = rect_L,
xmax = rect_R ,
ymin = rep("Seed collection", 12),
ymax = rep("Site preparation", 12),
season = season,
shades = shades
)
#-------- Do the graph ------
ggplot(act, aes(x = start, xend = end, y = task, yend = task, color = group)) +
geom_segment(size = 6) +
labs(title = "Schedule of Activities", x = "Date", y = "Task") +
theme_minimal() +
geom_area(data = shade, aes(xmin = xmin, xmax = xmax, ymin = ymin, ymax=ymax,
fill=shades, alpha=0.8))
As already suggested by @Kat in the comments, a geom_area
makes no sense and you should/could use a geom_rect
instead. Additionally, as you want a background shading I would suggest to switch the layers. Finally, to get a separate legend for the shadings and use an individual color palette I use the ggnewscale
package which allows for multiples scales and legends for the same aesthetic:
library(ggplot2)
library(ggnewscale)
cols_season <- setNames(
unique(shade$shades),
unique(shade$season)
)
shade$season <- factor(
shade$season,
c("winter", "spring", "summer", "autumn")
)
ggplot(act, aes(x = start, xend = end, y = task, yend = task, color = group)) +
geom_rect(
data = shade, aes(
xmin = xmin, xmax = xmax,
fill = season
), ymin = -Inf, ymax = Inf,
alpha = 0.2, inherit.aes = FALSE
) +
scale_fill_manual(
values = cols_season
) +
ggnewscale::new_scale_fill() +
geom_segment(size = 6) +
scale_fill_discrete() +
theme_minimal() +
labs(title = "Schedule of Activities", x = "Date", y = "Task")