facet_zoom can't change breaks of zoomed plot

1.1k Views Asked by At

I currently have a plot and have used facet_zoom to focus on records between 0 and 10 in the x axis. The following code reproduces an example:

require(ggplot2)
require(ggforce)
require(dplyr)
x <- rnorm(10000, 50, 25)
y <- rexp(10000)
data <- data.frame(x, y)

ggplot(data, aes(x = x, y = y)) +
  geom_point() +
  facet_zoom(x = dplyr::between(x, 0, 10))

I want to change the breaks on the zoomed portion of the graph to be the equivalent of:

ggplot(data, aes(x = x, y = y)) +
  geom_point() +
  facet_zoom(x = dplyr::between(x, 0, 10)) +
  scale_x_continuous(breaks = seq(0,10,2))

But this changes the breaks of the original plot as well. Is it possible to just change the breaks of the zoomed portion whilst leaving the original plot as default?

1

There are 1 best solutions below

0
On

This works for your use case:

ggplot(data, aes(x = x, y = y)) +
  geom_point() +
  facet_zoom(x = between(x, 0, 10)) +
  scale_x_continuous(breaks = pretty)

plot

From ?scale_x_continuous, breaks would accept the following (emphasis added):

One of:

  • NULL for no breaks
  • waiver() for the default breaks computed by the transformation object
  • A numeric vector of positions
  • A function that takes the limits as input and returns breaks as output

pretty() is one such function. It doesn't offer very fine control, but does allow you to have some leeway to specify breaks across different facets with very different scales.

For illustration, here are two examples with different desired number of breaks. See ?pretty for more details on the other arguments this function accepts.

p <- ggplot(data, aes(x = x, y = y)) +
  geom_point() +
  facet_zoom(x = between(x, 0, 10))

cowplot::plot_grid(
  p + scale_x_continuous(breaks = function(x) pretty(x, n = 3)),
  p + scale_x_continuous(breaks = function(x) pretty(x, n = 10)),
  labels = c("n = 3", "n = 10"),
  nrow = 1
)

more examples

Of course, you can also define your own function to convert plot limits into desired breaks, (e.g. something like p + scale_x_continuous(breaks = function(x) seq(min(x), max(x), length.out = 5))), but I generally find these functions require more tweaking to get right, & pretty() is often good enough.