Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Force y axis to start at 0, insert "break", AND have a large y axis using ggplot2 [duplicate]

Tags:

r

ggplot2

yaxis

I am still working on finalizing a reproducible figure for publication. Reviewers would like to see the below plot's y-axis start at 0 and include line break "//". The y-axis will need to not only be pretty large (think, 1500 units) but also zoomed in pretty tightly (think, 300 units). This makes the reviewer want us to add a line break to denote that our axis starts at 0, but continues on.

Example of what I can create:
enter image description here

Example of what I want (note the y axis; this was done manually in powerpoint in a similar figure):
enter image description here

My code:

ggplot(data = quad2,
       aes(x, predicted, group = group)) +
  geom_point(aes(shape = group), size = 6) +
  scale_shape_manual(values=c(19, 1)) +
  geom_line(size = 2,
            aes(linetype = group),
            color = "black") +
  scale_linetype_manual(values = c("solid", "dashed")) +
  geom_linerange(size = 1,
                 aes(ymin = predicted - conf.low,
                     ymax = predicted + conf.high),
                 color = "black",
                 alpha = .8) +
   geom_segment(aes(xend = x,
                    yend = ifelse(group == "Control", conf.high, conf.low)),
                arrow = arrow(angle = 90), color = "red")+
    labs(x = "Time",
       y = expression(bold("QUAD Volume (cm"^"3"*")")),
       linetype = "",
       shape = "") + #Legend title
  scale_y_continuous(limits =c(1500, 2000)) 

Reproducible data:

dput(quad2)
structure(list(x = structure(c(1L, 1L, 2L, 2L, 3L, 3L, 4L, 4L, 
5L, 5L), .Label = c("PRE", "MID1", "MID2", "MID3", "POST"), class = "factor"), 
    predicted = c(1666.97185871754, 1660.27445165342, 1743.2831065274, 
    1678.48945165342, 1788.50605542978, 1637.40907049806, 1807.55826371403, 
    1639.78265640012, 1865.8766220711, 1652.91070173056), std.error = c(88.8033117577884, 
    91.257045996107, 92.9973963841595, 95.3834973421298, 95.0283457128716, 
    97.3739053806999, 95.6466346849776, 97.9142418717957, 93.3512943191676, 
    95.5735155125126), conf.low = c(0, 91.257045996107, 0, 95.3834973421298, 
    0, 97.3739053806999, 0, 97.9142418717957, 0, 95.5735155125126
    ), conf.high = c(88.8033117577884, 0, 92.9973963841595, 0, 
    95.0283457128716, 0, 95.6466346849776, 0, 93.3512943191676, 
    0), group = structure(c(1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 
    2L), .Label = c("Intervention", "Control"), class = "factor")), class = "data.frame", row.names = c(NA, 
-10L))
like image 593
Millionhorns Avatar asked Oct 27 '25 09:10

Millionhorns


2 Answers

Plotting discontinuous axis is made difficult for a reason, that reason being that you should avoid doing it whenever possible. While I disagree with your reviewers, you can get down and dirty with the underlying grid graphics if you truly want a y-axis break.

First make your plot. The only thing I added was y-axis formatting and an axis line theme. We'll just label the bottom tick with "0".

plt <- ggplot(data = quad2,
       aes(x, predicted, group = group)) +
  geom_point(aes(shape = group), size = 6) +
  scale_shape_manual(values=c(19, 1)) +
  geom_line(size = 2,
            aes(linetype = group),
            color = "black") +
  scale_linetype_manual(values = c("solid", "dashed")) +
  geom_linerange(size = 1,
                 aes(ymin = predicted - conf.low,
                     ymax = predicted + conf.high),
                 color = "black",
                 alpha = .8) +
  geom_segment(aes(xend = x,
                   yend = ifelse(group == "Control", conf.high, conf.low)),
               arrow = arrow(angle = 90), color = "red")+
  labs(x = "Time",
       y = expression(bold("QUAD Volume (cm"^"3"*")")),
       linetype = "",
       shape = "") + #Legend title
  scale_y_continuous(limits =c(1400, 2000),
                     breaks = seq(1400, 2000, by = 200),
                     labels = c(0, seq(1600, 2000, by = 200)),
                     expand = c(0,0,0.05,0)) +
  theme(axis.line = element_line())

Then, we'll make this into a gtable and grab the y-axis line:

gt <- ggplotGrob(plt)

is_yaxis <- which(gt$layout$name == "axis-l")
yaxis <- gt$grobs[[is_yaxis]]

# You should grab the polyline child
yline <- yaxis$children[[1]]

Now we can edit the line as we see fit:

yline$x <- unit(rep(1, 4), "npc")
yline$y <- unit(c(0, 0.1, 1, 0.15), "npc")
yline$id <- c(1, 1, 2, 2)
yline$arrow <- arrow(angle = 90)

Place it back into the gtable object and plot it:

yaxis$children[[1]] <- yline

gt$grobs[[is_yaxis]] <- yaxis

# grid plotting syntax
grid.newpage(); grid.draw(gt)      

enter image description here

You can make stylistic choices at the line editing step as you see fit.

like image 168
teunbrand Avatar answered Oct 29 '25 23:10

teunbrand


To my knowledge ggplot2 doesn't support axis breaks. There is a solution here with facet_grid.

like image 44
yhy Avatar answered Oct 30 '25 00:10

yhy



Donate For Us

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