I have a line chart with metrics for different years and months. I want to add a median line for each month.
library(dplyr)
library(lubridate)
library(ggplot2)
set.seed(52)
data <- tibble(
date = seq.Date(from = as.Date("2017-01-01"), to = date("2020-12-31"), by = "month")
) %>%
mutate(
metric = rnorm(n(), mean = 5, sd = 2),
month = month(date, label = TRUE),
year = as.factor(year(date))
)
ggplot(data, aes(x = month, y = metric, color = year, group = year)) +
geom_line()

I tried using geom_hline() to do this but it only produces a line for the total median.
ggplot(data, aes(x = month, y = metric, color = year, group = year)) +
geom_line() +
geom_hline(aes(yintercept = median(metric), group = month))

Created on 2021-11-18 by the reprex package (v2.0.1)
What is the easiest way to create a median line for each month? Like this:

Is this what you are looking for...?
ggplot(data, aes(x = month, y = metric, color = year, group = year)) +
geom_line() +
geom_tile(data = function(df) df %>% group_by(month) %>%
summarise(metric = median(metric)),
aes(x = month, y = metric), height = 0.05, inherit.aes = FALSE)

Alternatively, thanks to @user20650's comment below, this also works...
ggplot(data, aes(x = month, y = metric, color = year, group = year)) +
geom_line() +
stat_summary(aes(x = month, y = metric),
fun = median,
geom = "tile",
height = 0.05,
inherit.aes = FALSE)
You could use ave.
I didn't get it if you need a median line for each year or through the months, so I will show you both.
ggplot(data, aes(x = month, y = metric, color = year, group = year)) +
geom_line() +
geom_line(aes(y = ave(metric, year, FUN = median)))

ggplot(data, aes(x = month, y = metric, color = year, group = year)) +
geom_line() +
geom_line(aes(y = ave(metric, month, FUN = median), colour = "median"), size = 2)

EDIT:
since you are interested in a horizontal line, here you have an alternative solution:
ggplot(data, aes(x = month, y = metric, color = year, group = year)) +
geom_line() +
stat_summary(aes(x = month, y=metric), fun = median, geom = "point", shape = "-", size = 15, inherit.aes = FALSE)

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With