I want to have axis ticks (breaks
) for the minimum value and maximum value observed in the data. But I do not want to do this manually because the code should scale to different datasets.
I have tried adapting https://stackoverflow.com/a/22819926/17724015, https://stackoverflow.com/a/5380817/17724015, and https://stackoverflow.com/a/52337662/17724015. What ggplot
options am I missing?
# situation
library(ggplot2)
dat <- data.frame(x = sample(letters), y = 1:26)
ggplot(dat, aes(x, y)) +
geom_tile() +
scale_y_reverse()
# required output
ggplot(dat, aes(x, y)) +
geom_tile() +
scale_y_reverse(breaks = c(1, 10, 20, 26))
# attempted solution (not suitable, not enough breaks)
ggplot(dat, aes(x, y)) +
geom_tile() +
scale_y_reverse(breaks = seq(min(dat$y), max(dat$y), by = mean(range(dat$y)) - 1))
# attempted solution (not scalable, too many breaks)
ggplot(dat, aes(x, y)) +
geom_tile() +
scale_y_reverse(n.breaks = nrow(dat) - 1)
# attempted solution (not working)
ggplot(dat, aes(x, y)) +
geom_tile() +
scale_y_reverse(expand = expansion(add = 1))
Created on 2023-11-16 with reprex v2.0.2
The default function for calculating breaks is scales::extended_breaks()
. You can run that function and modify the results as you see fit. (And the breaks
argument accepts a function.) Maybe something like this:
ggplot(dat, aes(x, y)) +
geom_tile() +
scale_y_reverse(breaks = \(y) {
eb = scales::extended_breaks()(y)
eb[1] = min(dat$y)
eb[length(eb)] = max(dat$y)
eb
})
I'm not sure of a good way to avoid hardcoding the data frame and y column here, but at least it's better than hardcoding the actual values. Perhaps someone else will know how to do that.