---
title: "Set Axis Break for ggplot2"
author: "Guangchuang Yu and Shuangbin Xu\\

        School of Basic Medical Sciences, Southern Medical University"
date: "`r Sys.Date()`"
output:
  prettydoc::html_pretty:
    toc: true
    theme: cayman
    highlight: github
  pdf_document:
    toc: true
vignette: >
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteIndexEntry{ggbreak introduction}
  %\VignetteDepends{ggplot2}
  %\VignetteDepends{grid}
  %\VignetteDepends{aplot}
  %\VignetteDepends{ggplotify}
  %\usepackage[utf8]{inputenc}
---



```{r include=FALSE}
knitr::opts_chunk$set(warning = FALSE,
                      message = TRUE)

library(ggplot2)
library(ggbreak)
library(patchwork)
library(yulab.utils)
```

## Introduction

This package was first designed to set breakpoints for truncating the plot as I need to shrink outlier long branch of a phylogenetic tree.


Axis break or a so-called gap plot is useful for large datasets that are not normally distributed and contain outliers. Sometimes we can transform the data (e.g. using log-transformation if the data was log-normal distributed) to solve this problem. But this is not always granted. The data may just simply contain outliers and these outliers are meaningful. A simple gap plot can solve this issue well to present the data in detail with both normal and extreme data. 


This package provides several scale functions to break down a 'gg' plot into pieces and align them together with (gap plot) or without (wrap plot or cut plot) ignoring subplots. Our methods are fully compatible with `ggplot2`, so that users can still use the `+` operator to add geometric layers after creating a broken axis.



If you use `r CRANpkg('ggbreak')` in published research, please cite the following paper:

+ S Xu<sup>#</sup>, M Chen<sup>#</sup>, T Feng, L Zhan, L Zhou, __G Yu__<sup>\*</sup>. Use ggbreak to effectively utilize plotting space to deal with large datasets and outliers. __*Frontiers in Genetics*__. 2021, 12:774846. doi: [10.3389/fgene.2021.774846](https://www.frontiersin.org/articles/10.3389/fgene.2021.774846/full/)


## Gap plot

For creating gap plot, we provide `scale_x_break` and `scale_y_break` functions. Multiple breakpoints on a single axis are supported, and you can also apply both functions to set breakpoints for both x and y axes simultaneously.

### Feature 1: Compatible with ggplot2

After breaking the plot, we can still superpose geometric layers and set themes. This ensures that users familiar with `ggplot2` can seamlessly adopt `ggbreak` without changing their workflow. The following example demonstrates adding a text layer and modifying the theme after applying an axis break.

```{r fig.keep="last"}
library(ggplot2)
library(ggbreak) 
library(patchwork)

set.seed(2019-01-19)
d <- data.frame(x = 1:20,
   y = c(rnorm(5) + 4, rnorm(5) + 20, rnorm(5) + 5, rnorm(5) + 22)
)
 
p1 <- ggplot(d, aes(y, x)) + geom_col(orientation="y")
d2 <- data.frame(x = c(2, 18), y = c(7, 26), label = c("hello", "world"))
p2 <- p1 + scale_x_break(c(7, 17)) + 
  geom_text(aes(y, x, label=label), data=d2, hjust=1, colour = 'firebrick')  + 
  xlab(NULL) + ylab(NULL) + theme_minimal()

p1 + p2
```

### Feature 2: Multiple break-points are supported

`ggbreak` allows users to specify multiple breakpoints on a single axis. This is particularly useful when the data contains multiple clusters of outliers or interesting regions separated by large empty intervals. You can simply add multiple `scale_x_break()` layers to the plot.

```{r}
p2 + scale_x_break(c(18, 21))
```

### Feature 3: Simultaneous breaks on both x and y axes

You can combine `scale_x_break()` and `scale_y_break()` to create dual-axis break plots. This is particularly useful when you have data points that form distinct clusters with large gaps in between on both dimensions. The package handles the layout and alignment automatically.

```{r fig.width=8, fig.height=6}
set.seed(2023-01-01)
df <- data.frame(
    x = c(rnorm(50, 5, 1), rnorm(10, 50, 2)),
    y = c(rnorm(50, 10, 2), rnorm(10, 100, 5)),
    group = c(rep("Cluster 1", 50), rep("Cluster 2", 10))
)

ggplot(df, aes(x, y, color = group)) + 
    geom_point(size = 3) +
    scale_x_break(c(10, 45)) + 
    scale_y_break(c(20, 90)) +
    theme_bw() +
    theme(legend.position = "top")
```

Multiple breaks on both axes are also supported. This feature enables complex visualizations where data is distributed across multiple disjoint regions in a 2D space.

```{r fig.width=8, fig.height=6}
ggplot(df, aes(x, y, color = group)) + 
    geom_point(size = 3) +
    scale_x_break(c(10, 20)) + 
    scale_x_break(c(30, 45)) + 
    scale_y_break(c(20, 40)) + 
    scale_y_break(c(60, 90)) +
    theme_bw() +
    theme(legend.position = "top")
```

### Feature 4: Axis break symbols

You can add standard axis break symbols (like a double-slash `//`) to the axes where they are broken by using the `symbol` parameter. This visual cue helps readers quickly identify that the axis is discontinuous. Currently, `symbol = "slash"` is supported, and it works for both single and dual axis breaks.

```{r fig.width=8, fig.height=4}
ggplot(mpg, aes(displ, hwy)) +
    geom_point() +
    scale_x_break(c(3, 4), symbol = "slash")
```

### Feature 5: Zoom in or zoom out of subplots

The `scales` parameter allows you to control the relative size of the subplots. This is useful when you want to zoom in on a specific range of data to show more detail, or zoom out to show the overall trend. A value larger than 1 zooms in (allocates more space), while a value smaller than 1 zooms out.

```{r}
p1 + scale_x_break(c(7, 17), scales = 1.5) + scale_x_break(c(18, 21), scales=2)
```

### Feature 6: Support reverse scale

`ggbreak` works seamlessly with `scale_y_reverse()` (and `scale_x_reverse()`). This is common in fields like oceanography or atmospheric science where depth or pressure is plotted on a reversed axis. The break function respects the reversed direction of the axis.

```{r fig.keep='last'}
g <- ggplot(d, aes(x, y)) + geom_col()
g2 <- g + scale_y_break(c(7, 17), scales = 1.5) + 
  scale_y_break(c(18, 21), scale=2) + scale_y_reverse()
g + g2
```

### Feature 7: Compatible with scale transform functions

Users can apply scale transform functions, such as `scale_x_log10` and `scale_x_sqrt`, to an axis break plot. This allows for handling data that spans several orders of magnitude while still excluding uninteresting ranges.

```{r fig.keep='last', fig.width=10, fig.height=5}
p2 <- p1 + scale_x_break(c(7, 17)) 
p3 <- p1 + scale_x_break(c(7, 17)) + scale_x_log10()
p2 + p3
```

### Feature 8: Compatible with `coord_flip`

Flipping the coordinate system with `coord_flip()` is fully supported. This is often used to create horizontal bar charts or to swap axes for better readability. `ggbreak` detects the flip and adjusts the axis breaks accordingly.

```{r message=FALSE}
g + coord_flip() + scale_y_break(c(7, 18))
```


### Feature 9: Compatible with `facet_grid` and `facet_wrap`

`ggbreak` can be used in conjunction with faceting functions like `facet_grid()` and `facet_wrap()`. This allows you to create small multiples where each panel has a broken axis, which is extremely powerful for comparing distributions across different groups.

```{r message=FALSE}
set.seed(2019-01-19)
d <- data.frame(
  x = 1:20,
  y = c(rnorm(5) + 4, rnorm(5) + 20, rnorm(5) + 5, rnorm(5) + 22),
  group = c(rep("A", 10), rep("B", 10)),
  face=c(rep("C", 5), rep("D", 5), rep("E", 5), rep("F", 5))
)

p <- ggplot(d, aes(x=x, y=y)) +
     geom_col(orientation="x") +
     scale_y_reverse() +
     facet_wrap(group~.,
                scales="free_y",
                strip.position="right",
                nrow=2
                ) +
     coord_flip()
pg <- p +
  scale_y_break(c(7, 17), scales="free") +
  scale_y_break(c(19, 21), scales="free")
print(pg)
```



### Feature 10: Compatible with legends

Legends are automatically handled and preserved. You can position the legend anywhere using `theme(legend.position = ...)`. In this example, we move the legend to the bottom of the plot.

```{r message=FALSE}
pg <- pg + aes(fill=group) + theme(legend.position = "bottom")
print(pg)
```

### Feature 11: Supports all plot labels

All standard plot labels, including title, subtitle, caption, and tag, are supported and correctly placed around the broken plot. Standard theme elements for these labels (like font size, face, and position) are also respected.

```{r message=FALSE}
pg + labs(title="test title", subtitle="test subtitle", tag="A tag", caption="A caption") +
     theme_bw() +
     theme(
           legend.position = "bottom",
           strip.placement = "outside",
           axis.title.x=element_text(size=10),
           plot.title = element_text(size = 22),
           plot.subtitle = element_text(size = 16),
           plot.tag = element_text(size = 10),
           plot.title.position = "plot",
           plot.tag.position = "topright",
           plot.caption = element_text(face="bold.italic"),

     )
```

### Feature 12: Allows setting tick labels for subplots

Sometimes you might want specific control over the tick labels in each subplot segment. The `ticklabels` argument allows you to manually specify which labels should appear in each broken segment, overriding the default breaks.

```{r message=FALSE, fig.width=10, fig.height=6}
require(ggplot2)
library(ggbreak)
set.seed(2019-01-19)
d <- data.frame(
  x = 1:20,
  y =  c(rnorm(5) + 4, rnorm(5) + 20, rnorm(5) + 5, rnorm(5) + 22),
  group = c(rep("A", 10), rep("B", 10))
)

p <- ggplot(d, aes(x=x, y=y)) +
     scale_y_reverse() +
     scale_x_reverse() +
     geom_col(aes(fill=group)) +
     scale_fill_manual(values=c("#00AED7", "#009E73")) +
     facet_wrap(
         group~.,
         scales="free_y",
         strip.position="right",
         nrow=2
     ) +
     coord_flip()                                                                                                                                                                                                  

p +
     scale_y_break(c(7, 10), scales=0.5, ticklabels=c(10, 11.5, 13)) +
     scale_y_break(c(13, 17), scales=0.5, ticklabels=c(17, 18, 19)) +
     scale_y_break(c(19,21), scales=1, ticklabels=c(21, 22, 23))
```

The `breaks` argument of `scale_x_break()` and `scale_y_break()` is the place where the axis is cut, not where the ticks are drawn. To set the ticks, pass `breaks` to the continuous scale instead. Every subplot then keeps the breaks that fall in its own range, which is how the grid lines are made to line up across the subplots:

```{r message=FALSE, fig.width=10, fig.height=4}
set.seed(1)
d <- data.frame(
  x = c(seq(0, 40, length.out = 40), seq(80, 88, length.out = 20)),
  y = rnorm(60, 10, 3)
)
p <- ggplot(d, aes(x, y)) + geom_point()

p + scale_x_break(c(50, 70))

p + scale_x_continuous(breaks = seq(0, 90, by = 10)) +
    scale_x_break(c(50, 70))
```

The second plot has a tick every 10 units on both sides of the break. The first one does not, because `ggplot2` picks a `pretty()` interval from the range of each subplot on its own, and the left subplot spans 0 to 50 while the right one spans only 70 to 88.

### Feature 13: Compatible with dual axis

`ggbreak` works correctly with `scale_y_continuous(sec.axis = ...)` to create dual y-axes (e.g., metric vs imperial units). The secondary axis is broken in sync with the primary axis.

```{r fig.width=10, fig.height=5}
p <- ggplot(mpg, aes(displ, hwy)) +
     geom_point() +
     scale_y_continuous(
       "mpg (US)",
       sec.axis = sec_axis(~ . * 1.20, name = "mpg (UK)")
     ) +
      theme(
        axis.title.y.left = element_text(color="deepskyblue"),
        axis.title.y.right = element_text(color = "orange")
      )
p1 <- p + scale_y_break(breaks = c(20, 30))
p2 <- p + scale_x_break(breaks = c(3, 4))
p1 + p2
```

### Feature 14: Compatible with patchwork

`ggbreak` objects are fully compatible with `patchwork`. This means you can combine multiple broken plots, or combine broken plots with standard ggplot objects, into a single composite figure using simple arithmetic operators like `+` or `/`.

```{r message=FALSE, fig.width=8, fig.height=5, fig.keep="last"}
library(patchwork)

set.seed(2019-01-19)
d <- data.frame(
               x = 1:20,
               y = c(rnorm(5) + 4, rnorm(5) + 20, rnorm(5) + 5, rnorm(5) + 22)
)

p <- ggplot(d, aes(x, y)) + geom_col()
x <- p+scale_y_break(c(7, 17 ))

x + p
```

### Feature 15: Axis breaks on a discrete axis

`scale_x_break()` and `scale_y_break()` are not limited to continuous axes. They also work on a categorical axis, such as the class of a car in `mpg` or a set of experimental conditions, which is convenient when the categories are not all equally interesting and the space spent on the ones you do not care about can be given to the ones you do. The break points are level names instead of numbers.

```{r fig.width=8, fig.height=4}
ggplot(mpg, aes(class, hwy)) +
    geom_boxplot() +
    scale_x_break(c("compact", "midsize"), space = 0.5)
```

`compact` and `midsize` are adjacent levels of `mpg$class`, so this break only inserts a gap between them: all seven categories are still drawn, but `2seater` and `compact` are moved into a subplot of their own. The `space` argument is the width of the gap in centimetres, and its default is 0.1 cm. Enlarging it is often worth it here, because the two halves of the axis carry no visual cue other than the gap that they are not contiguous.

A break interval that spans several levels behaves like a break on a continuous axis: the levels lying strictly between the two ends of the interval are dropped. Below, `midsize` and `minivan` disappear from the plot, so the remaining categories are packed closer together and each of them is given more room.

```{r fig.width=8, fig.height=4}
ggplot(mpg, aes(class, hwy)) +
    geom_boxplot() +
    scale_x_break(c("compact", "pickup"), space = 0.5)
```

This is the categorical counterpart of a break that hides a range of a continuous axis: it removes part of the axis you are not interested in and hands the freed space over to the rest of the plot. Note that the two ends of the interval are the levels that are *kept* on either side, so `scale_x_break(c("compact", "pickup"))` draws `compact` and `pickup` and drops what lies between them.

Everything above also applies to a vertical axis, and `scale_x_cut()` and `scale_y_cut()` accept level names as well.

```{r fig.width=8, fig.height=4}
ggplot(mpg, aes(hwy, class)) +
    geom_boxplot() +
    scale_y_break(c("compact", "midsize"), space = 0.5)

ggplot(mpg, aes(class, hwy)) +
    geom_boxplot() +
    scale_x_cut("midsize", which = 2, scales = 2, space = 0.5)
```

A cut is the right choice when the categories next to the boundary still have to be read against each other: unlike a break, it keeps the level at the boundary in *both* slices, so `midsize` appears twice and each slice can be compared with it. Here the second slice is also zoomed in with `scales = 2`, which is the same argument that zooms in on a continuous cut.

### Feature 16: Date and datetime axes

An axis break can be placed on a `Date` or a `POSIXct` axis, which is what you need for a time series whose early and late parts are far apart in time while the middle is not worth the space. The break points may be given as `Date`, as `POSIXct`, as a character string such as `"2026-01-04"`, or as a number, which is read as days since the epoch on a `Date` axis and as seconds since the epoch on a datetime one.

```{r fig.width=8, fig.height=4}
ggplot(economics, aes(date, unemploy)) +
    geom_line() +
    scale_x_break(as.Date(c("1980-01-01", "1990-01-01")), space = 0.5)
```

Here the unemployment series of `economics` is broken into the period before 1980 and the period after 1990. Note that the axis still carries dates, not numbers: `ggbreak` keeps the scale that `ggplot2` derives from the data, so you do not have to add a `scale_x_date()` call of your own before breaking the axis.

A character break point is read as a wall clock time on the axis, which is convenient when the break should fall at a natural boundary such as midnight.

```{r fig.width=8, fig.height=4}
set.seed(2019-01-19)
t0 <- as.POSIXct("2026-01-01 00:00:00", tz = "UTC")
d3 <- data.frame(
    time = t0 + (0:239) * 3600,
    value = c(rnorm(80) + 5, rnorm(80) + 50, rnorm(80) + 6)
)

ggplot(d3, aes(time, value)) +
    geom_point() +
    scale_x_break(c("2026-01-04", "2026-01-07"), space = 0.5)
```

The two features combine, so a datetime axis can be paired with a break on the other axis, and neither axis loses its labels.

```{r fig.width=8, fig.height=4}
ggplot(d3, aes(time, value)) +
    geom_point() +
    scale_y_break(c(10, 45), space = 0.5)
```

### Feature 17: Compatible with `ggrepel`

Labels created by `ggrepel::geom_text_repel()` or `ggrepel::geom_label_repel()` are drawn in the subplot that holds their point, and only there. `ggrepel` lays its labels out in the coordinate system of the panel and keeps them inside it, so without this a label would be pushed to the edge of every subplot instead of being clipped away with the rest of the data, and the labels of the other subplots would pile up along that edge.

```{r eval=requireNamespace("ggrepel", quietly=TRUE), fig.width=8, fig.height=4}
set.seed(2019-01-19)
d4 <- data.frame(
    x = 1:24,
    y = c(rnorm(12) + 4, rnorm(12) + 20),
    label = letters[1:24]
)

ggplot(d4, aes(x, y)) +
    geom_point() +
    ggrepel::geom_text_repel(aes(label = label), seed = 1) +
    scale_y_break(c(7, 17), space = 0.5)
```

The points above the break are labelled `m` to `x` and the points below it are labelled `a` to `l`, and no label of one group shows up in the subplot of the other. `ggrepel` keeps pushing the labels of a subplot apart as usual, so a crowded panel is still readable. The `seed` argument of `ggrepel` is honoured, which makes such a plot reproducible.

### Feature 18: Join up a line that crosses a break

A break hides a range of the axis and draws what is left in separate subplots, so a line that runs across the break stops at the edge of one subplot and starts again at the edge of the next. The two ends sit at different positions along the broken axis, because the piece that joins them lies in the range the break hides and no subplot is drawn there. A line keeps its whole geometry until it is drawn, though, so where it leaves one subplot and enters the next can be read off it, and the blank space that `space` opens between the subplots is exactly where that piece belongs.

`scale_x_break()` and `scale_y_break()` take a `bridge` argument, off by default. Without it, a connected scatter plot reads as two lines.

```{r fig.width=7, fig.height=4}
d5 <- data.frame(x = 1:10, y = c(1, 2, 3, 4, 5, 50, 55, 60, 65, 70))

ggplot(d5, aes(x, y)) +
    geom_point() +
    geom_line() +
    scale_y_break(c(10, 45), space = 0.5)
```

With `bridge = TRUE` the piece the break hides is drawn in the gap, so the line runs from the first point to the last one, with a short flatter segment where the break is.

```{r fig.width=7, fig.height=4}
ggplot(d5, aes(x, y)) +
    geom_point() +
    geom_line() +
    scale_y_break(c(10, 45), space = 0.5, bridge = TRUE)
```

The bridge is drawn in the space between the subplots, so a larger `space` makes it more visible. The lines of `geom_line()`, `geom_path()` and `geom_step()` are bridged, and only for a single break on a continuous axis. On a discrete axis a subplot keeps only its own levels, so its line stops at its own levels and never reaches the edge of the panel; a plot that is faceted along the broken axis binds the subplots into a facet grid rather than stacking them, so the two ends are not across from each other. Points and ribbons are not bridged.

## Wrap plot

The `scale_wrap()` function wraps a 'gg' plot over multiple rows to make plots with long x-axes easier to read. It is the complement of `scale_x_break()`: a break hides a range of the axis and draws what is left next to each other, while a wrap keeps the whole axis and splits it into `n` consecutive windows of the same width, one per row. Each window is drawn at the full width of the figure, so a long series becomes readable without dropping anything from it.

```{r fig.width=6, fig.height=8}
p <- ggplot(economics, aes(x=date, y = unemploy, colour = uempmed)) +
  geom_line()

p + scale_wrap(n=4)
```

Both categorical and numerical variables are supported. On a categorical axis the levels are divided over the windows instead of the range being cut into equal pieces, so the categories keep their own order.

```{r fig.width=7, fig.height=6}
ggplot(mpg, aes(class, hwy)) + 
  geom_boxplot() +
      scale_wrap(n = 2)
```

## Cut plot

The `scale_x_cut` or `scale_y_cut` cuts a 'gg' plot to several slices with the ability to specify which subplots to zoom in or zoom out. A cut differs from a break in that the break points become boundaries of the slices: the data right next to a boundary is kept in both of the slices it separates, so a trend that crosses the boundary can still be followed across the two of them. The `which` argument selects the slices to zoom, and `scales` says by how much, exactly as it does for `scale_x_break()`.

```{r}
library(ggplot2)
library(ggbreak)
set.seed(2019-01-19)
d <- data.frame(
     x = 1:20,
     y = c(rnorm(5) + 4, rnorm(5) + 20, rnorm(5) + 5, rnorm(5) + 22)
 )
p <- ggplot(d, aes(x, y)) + geom_col()
p + scale_y_cut(breaks=c(7, 18), which=c(1, 3), scales=c(3, 0.5))
```

Here the axis is cut at 7 and 18, which gives three slices, and the first and the third of them are enlarged three times and shrunk by half respectively, while the middle one keeps its size.

## Adjust the amount of space between subplots

The `space` parameter in `scale_x_break()`, `scale_y_break()`, `scale_x_cut()` and `scale_y_cut()` allows user to control the space between subplots. It is a length in centimetres, 0.1 cm by default, and it is added to the margin of the subplots. The gap between two subplots is what tells the reader that the axis is not continuous, so a wider `space` is often worth setting when a plot is meant to be read by someone who does not already know where the breaks are.

```{r}
p + scale_y_cut(breaks=c(7, 18), which=c(1, 3), scales=c(3, 0.5), space=.5)
```

## Place legend at any position

A legend is drawn once for the whole broken plot, and its position is controlled by the usual `theme(legend.position = ...)`. A manual position such as `theme(legend.position = c(.1, .2))` is the one case that cannot be honoured directly, because the figure is assembled from several subplots. The workaround is to take the legend out of the plot and put it back at the end, which also gives you full control over where it lands.

```{r legend-subview, fig.keep="last"}
## original plot
p1 <- ggplot(mpg, aes(displ, hwy, color=factor(cyl))) + geom_point()

## ggbreak plot without legend
p2 <- p1 + scale_x_break(c(3, 4)) +
    theme(legend.position="none") 

## extract legend from original plot
leg = ggfun::get_legend(p1)

## redraw the figure
p3 <- ggplotify::as.ggplot(print(p2))

## place the legend 
p3 + ggimage::geom_subview(x=.9, y=.8, subview=leg)
```

The legend is extracted from the original plot, the broken plot is turned into a single 'gg' object with `ggplotify::as.ggplot()`, and the legend is then placed on top of it with `ggimage::geom_subview()`, whose `x` and `y` are the coordinates of the legend in the panel, from 0 to 1.



## Note

The features we introduced for `scale_x_break` and `scale_y_break` also work for `scale_wrap`, `scale_x_cut` and `scale_y_cut`. That includes the transformed and reverse scales, `coord_flip()`, faceting, dual axes, `patchwork`, and the discrete and date or datetime axes, so the choice between the five scale functions is only about how the axis should be rearranged and never about what is supported. The `symbol` argument is the exception: it marks the break on the axis and belongs to `scale_x_break()` and `scale_y_break()` only.

A plot can carry two of these scales, but only one pair of them: a break on the x axis together with a break on the y axis (`scale_x_break()` with `scale_y_break()`, see Feature 3). A wrapping, breaking or cutting scale cannot be used together with a different one of them, and a cut cannot be combined with anything at all. A wrap and a break both rearrange their own axis and both want to stack their windows along the figure, so the two of them together have no single layout the call could mean: one y break inside each wrap window, or one wrap window beside the other within each y window. Rather than draw a figure that looks plausible and is not, combining them is an error that names the two scales.

```{r, eval=FALSE}
p + scale_wrap(n = 2) + scale_y_break(c(10, 90))
#> Error in `check_scale_combination()`:
#> ! `scale_y_break()` cannot be combined with `scale_wrap()`.
#> ℹ A plot can be broken on both axes (`scale_x_break()` with `scale_y_break()`)
#>   and one axis can be cut, but a wrapping, breaking or cutting scale cannot be
#>   used together with a different one of them.
```

A broken plot is drawn by clipping rather than by cutting the data: every window is given the whole dataset and its panel hides the part that belongs to the other windows. What a panel hides is not written to the file, so a PDF or an SVG written from a broken plot holds no object larger than the figure and can be pasted into an editor such as Adobe Illustrator, which refuses a file whose objects are too large to paste.

## FAQ

1. Incompatible with functions that arrange multiple plots

You can use `aplot::plot_list()` to arrange `ggbreak` objects with other `ggplot` objects, and `patchwork`, `cowplot::plot_grid()` and `gridExtra::grid.arrange()` work directly as well since `ggbreak` 0.2.0. Before 0.2.0 these functions took the plot through `ggplotGrob()`, which built it without the break, so the break was dropped without a warning and the workaround was to call `print()` on the `ggbreak` object first, see also <https://github.com/YuLab-SMU/ggbreak/issues/36> and <https://github.com/YuLab-SMU/ggbreak/issues/37>.

2. `Some breaks are not in the plot range. Please check all breaks!`

The subplots are built by splicing the break points into the range of the axis, so every break point has to lie inside that range. A break such as `scale_y_break(c(10, 20))` on a plot whose `y` spans 4 to 6 cannot be drawn, and `ggbreak` reports it rather than silently flipping the axis of a subplot. The same message is produced by a break point that is not a level of the axis, or that is given out of order, when the axis is discrete.

3. The axis of a subplot is drawn as numbers

This used to happen when a `Date` or datetime axis was broken without an explicit `scale_x_date()` or `scale_x_datetime()` call, which turned the axis into days or seconds since the epoch. Recent versions of `ggbreak` keep the scale that `ggplot2` derives from the data, so the labels stay as dates. On an older version, adding the scale explicitly before the break is the workaround:

```{r eval=FALSE}
ggplot(economics, aes(date, unemploy)) +
    geom_line() +
    scale_x_date() +
    scale_x_break(as.Date(c("1980-01-01", "1990-01-01")))
```

