'Get axis limits from ggplot object [duplicate]

Sometimes I will make two plots that are similair, but have different data. As such, the X- and Y-axis will have different ranges.

library(ggplot2)
library(ggpubr)
#> Loading required package: magrittr
df1 <- data.frame(x=runif(10)*2,y = runif(10)*2)
df2 <- data.frame(x=runif(10)*3,y = runif(10)*1)
p1 <- qplot(x = x, y = y, data = df1, geom = "line")
p2 <- qplot(x = x, y = y, data = df2, geom = "line")

ggarrange(p1,p2)

Created on 2020-07-09 by the reprex package (v0.3.0)

This can manually be overcome by explicitly stating a range with xlim and ylim, but this is both tiresome and could lead to some data being outside of the specified range if one is not careful.

An ideal solution would be to dynamically obtain the limits from the p1, and if these are larger than those of p2, use those instead for p2. For example p2 + xlim(getLimits(p1)).

Is something like this supported?

EDIT: This question was suggested, but the answer applies to an older version of ggplot2. Additionally, the supported p1$coordinates$limits only return the manually specified limits, which defeats the purpose.



Solution 1:[1]

ggplot now has layer_*** convenience functions for extracting information from ggplots. In this case you can use the layer_scales function:

layer_scales(p1)$y$get_limits()

[1] 0.1499588 1.9527970

So you could do something like:

library(tidyverse)
library(patchwork)
library(ggpubr)
theme_set(theme_bw())

set.seed(2)
df1 <- data.frame(x=runif(10)*2,y = runif(10)*2)
df2 <- data.frame(x=runif(10)*3,y = runif(10)*1)
p1 <- qplot(x = x, y = y, data = df1, geom = "line")
p2 <- qplot(x = x, y = y, data = df2, geom = "line")

fnc = function(...) {
  
  p = list(...)
  
  yr = map(p, ~layer_scales(.x)$y$get_limits()) %>% 
    unlist %>% range
  
  xr = map(p, ~layer_scales(.x)$x$get_limits()) %>% 
    unlist %>% range
  
  p %>% map(~.x + xlim(xr) + ylim(yr))
}

wrap_plots(fnc(p1, p2))

enter image description here

Solution 2:[2]

Just draw one graph instead of two:

library(dplyr)
library(ggplot2)

# 1. create datasets
df1 <- data.frame(x=runif(10)*2, y = runif(10)*2)
df2 <- data.frame(x=runif(10)*3, y = runif(10)*1)


# 2. union datasets and plot
df1 %>% 
  mutate(dataset_name = "Dataframe #1") %>% 
  bind_rows(df2 %>% mutate(dataset_name = "Dataframe #2")) %>% 

  ggplot(aes(x = x, y = y)) +
    geom_line() +
    facet_grid(~ dataset_name)

enter image description here

Solution 3:[3]

Sounds like you're looking for ggplot_build()? The output of that function includes a panel object which contains axis limits. You can read more about it here. This is to get the panel object:

panel1 <- ggplot_build(p1)$panel
panel2 <- ggplot_build(p2)$panel

And then you can extract the ranges for x and y from there. The exact specifics depends on your installation version of ggplot2. Hope this helps.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2
Solution 3 Kel Varnsen