I would like to add frequencies on a second y-axis to a ridgeline plot using ggplot2
and ggridges
I found a tutorial adding the frequencies as numbers with geom_text
(https://rdrr.io/cran/ggridges/man/stat_binline.html), however, I would prefer to add them as a second y-axis.
Of course I very appreciate solutions outside ggridges
to get a similar plot.
Example data:
library(ggplot2)
library(ggridges)
library(lubridate)
# datapoints
data_timepoint <- data.frame(type=factor(c("A","B","C","D")),
start=as.Date(c("1990-01-01","2000-01-01","2010-01-01","2012-01-01")),
stop=as.Date(c(rep("2022-01-01",4))))
# frequencies
data_freq <- data.frame(type=c("A","A","B","C","D","D","D"),
year=ymd(year(as.Date(c("1991-01-01","1991-01-01","2005-01-01","2016-01-01","2013-01-01","2013-01-01","2015-01-01"))),truncated=2L))
# plot
ggplot(data_timepoint) +
geom_rect(aes(xmin=start, xmax=stop,
ymin=type, ymax=as.numeric(type)+0.9), fill="lightblue") +
geom_density_ridges(data=data_freq, aes(x=year,y=type),stat = "binline",
bins = 1, scale = 0.95, draw_baseline = FALSE, alpha=.5, binwidth=10,center=20) +
scale_x_date(date_breaks = "1 year",date_labels = "%Y") +
theme(axis.text.x = element_text(angle = 90),
axis.text.y = element_text(vjust = -2)) +
labs(title="",y="Type",x="Year")
Created on 2022-06-03 by the reprex package (v2.0.1)
You technically don't really have a secondary y axis - you just want to show frequency instead of density. You can generally show frequency by using
..count..
or with newer syntaxafter_stat(count)
as your y aesthetic. ggridges doesn't seem to have count as a computed stat - therefore maybe fake your ggridges look with facets.The example is adapted from ?geom_density_ridges
Created on 2022-06-03 by the reprex package (v2.0.1)
If you go a step further, and let the facets overlap (which is the principle of a ridge plot: overlapping facets of a density plot), you will see that by adding an axis guide to a classic ridge plot, there will be overlap of those guides between the ridges (your facets). This doesn't look good.
This is irrespective of your stat, and will also happen with stat = "binline"
To add your desired rectangle annotation, your approach is perfectly fine. Is the data actually structured as in your example or have you just created the second frame beforehand based on the first one? (This would be excellent and well done doing so)
Few more comments in the code