ChatGPT解决这个技术问题 Extra ChatGPT

How can I extract plot axes' ranges for a ggplot2 object?

I have an object from ggplot2, say myPlot, how can I identify the ranges for the x and y axes?

It doesn't seem to be a simple multiple of the data values' range, because one can rescale plots, modify axes' ranges, and so on. findFn (from sos) and Google don't seem to be turning up relevant results, other than how to set the axes' ranges.

I'm fairly sure that can't be extracted directly from the plot object itself, but you can infer it (in simple cases) from your data and the default values for expand. See here.
I was referring to the expand argument to the scale_* functions in ggplot. For example, see the defaults listed here.
You will be able to extract it in the next version...
Could you please accept Alex Holcombe's answer instead? Paul Hiemstra's is only relevant for versions of ggplot2 from over three years ago.
**As of Aug 2018 you extract the x and y-axes ranges with the following . ** ggplot_build(obj)$layout$panel_scales_x[[1]]$range$range ggplot_build(obj)$layout$panel_scales_y[[1]]$range$range

T
TheRimalaya

I am using ggplot2 version 2, I am not sure if this is same is previous version, Suppose you have saved your plot on plt object. It is easy to extract the ranges,

# y-range
layer_scales(plt)$y$range$range

# x-range
layer_scales(plt)$x$range$range

In case of facet plot, you can access scales of individual facets using layer_scales(plot, row_idx, col_idx). For example to access the facet at first row and second column,

# y-range
layer_scales(plt, 1, 2)$y$range$range

# x-range
layer_scales(plt, 1, 2)$x$range$range

And version 3.1.0
Note this gives you the range of the data to be plotted - to get the full axis range you will need to allow for the scale expansion. Moreover, if limits have been set (e.g. via ylim or coord_cartesian) the scale expansion will be applied to these limits rather than those returned by the code given here.
Note that the range does not include the expand. My default is to use an expand of expansion = mult(c(0, 0.25)), so a y scale of [0, 10] will practically/visibly become [0, 12], though $y$range$range returns [0, 10].
P
Paul Hiemstra

In newer versions of ggplot2, you can find this information among the output of ggplot_build(p), where p is your ggplot object.

For older versions of ggplot (< 0.8.9), the following solution works:

And until Hadley releases the new version, this might be helpful. If you do not set the limits in the plot, there will be no info in the ggplot object. However, in that case you case you can use the defaults of ggplot2 and get the xlim and ylim from the data.

> ggobj = ggplot(aes(x = speed, y = dist), data = cars) + geom_line()
> ggobj$coordinates$limits

$x
NULL

$y
NULL

Once you set the limits, they become available in the object:

> bla = ggobj + coord_cartesian(xlim = c(5,10))
> bla$coordinates$limits
$x
[1]  5 10

$y
NULL

Specifically, in the newer versions of ggplot2, you can get the yrange with ggplot_build(ggobj)$panel$ranges[[1]]$y.range and the xrange with ggplot_build(ggobj)$panel$ranges[[1]]$x.range
For ggplot2 version 2.1.0.9001 use this R code: ggplot_build(obj)$layout$panel_ranges[[1]]$x.range ggplot_build(obj)$layout$panel_ranges[[1]]$y.range
For ggplot2 version 2.2.1.9000 and (most probably) newer use this R code: ggplot_build(obj)$layout$panel_scales_x[[1]]$range$range ggplot_build(obj)$layout$panel_scales_y[[1]]$range$range
Is there no way to do it dynamically within the original plot call?
In 2.2.1 you can also use layer_scales(ggobj)$y$range$range
C
Community

November 2018 UPDATE

As of ggplot2 version 3.1.0, the following works:

obj <- qplot(mtcars$disp, bins = 5)

# x range
ggplot_build(obj)$layout$panel_params[[1]]$x.range

# y range
ggplot_build(obj)$layout$panel_params[[1]]$y.range

A convenience function:

get_plot_limits <- function(plot) {
    gb = ggplot_build(plot)
    xmin = gb$layout$panel_params[[1]]$x.range[1]
    xmax = gb$layout$panel_params[[1]]$x.range[2]
    ymin = gb$layout$panel_params[[1]]$y.range[1]
    ymax = gb$layout$panel_params[[1]]$y.range[2]
    list(xmin = xmin, xmax = xmax, ymin = ymin, ymax = ymax)
}
get_plot_limits(p)

Until the next update...


Suggested an edit with a convenience function, roll-back if you don't like it. ;-)
@PatrickT your update is really convenient. I really appreciate it :)
To get the x and y axis limits as a data frame, you can use purrr::map_df(.x=ggplot_build(obj)$layout$panel_params, .f=function(a) {setNames(object=c(a$x.range, a$y.range), nm=c("xMin", "xMax", "yMin", "yMax"))}) where obj is a ggplot object. This is especially useful for facet plots with scales="free". If someone knows how to add column(s) indicating the corresponding facet variable values, I'd love to see that code.
A
Alex Holcombe

Get the yrange with

ggplot_build(myPlot)$panel$ranges[[1]]$y.range 

and the xrange with

ggplot_build(myPlot)$panel$ranges[[1]]$x.range

These solutions work well for continuous numeric axes, but how can one handle axes with dates (continuous scale) or categorical values? When I use this method I get large numeric values that require some conversion to date format in order to add text using geom_text.
What if I am not setting the axis limits but using what ggplot suggests by default? My use case is that I like the default values for plot 1 but I want plot 2 to have the same axis limits as plot 1.
p
pat-s

In version 2.2.0 this has to be done as follows:

# y-range
ggplot_build(plot.object)$layout$panel_ranges[[1]]$y.range
# x-range
ggplot_build(plot.object)$layout$panel_ranges[[1]]$x.range

T
Tung

As of Aug 2018 you extract the x and y-axes ranges with the following.

ggplot_build(obj)$layout$panel_scales_x[[1]]$range$range ggplot_build(obj)$layout$panel_scales_y[[1]]$range$range


F
Frederik

As mentioned here: https://gist.github.com/tomhopper/9076152#gistcomment-2624958 there is a difference between the two options:

#get ranges of the data
ggplot_build(obj)$layout$panel_scales_x[[1]]$range$range 
ggplot_build(obj)$layout$panel_scales_y[[1]]$range$range

#get ranges of the plot axis
ggplot_build(obj)$layout$panel_params[[1]]$x.range
ggplot_build(obj)$layout$panel_params[[1]]$y.range

Here is a set of convenience functions to take a list of plots, extract the common y-axis range and replace it. I needed it because I used different data sets within one graph arranged via ggarange :

require(ggplot2)
#get the visible scales from single plots
get_plot_view_ylimits <- function(plot) {
  gb = ggplot_build(plot)
  ymin = gb$layout$panel_params[[1]]$y.range[1]
  ymax = gb$layout$panel_params[[1]]$y.range[2]
  message(paste("limits are:",ymin,ymax))
  list(ymin = ymin, ymax = ymax)
}

#change the limit of single plot, using list of limits
change_plot_ylimits <- function(plot, nlimits){
  p <- plot + ggplot2:::limits(unlist(nlimits, use.names =FALSE),"y")
}

#adjust the scales of multiple plots
#take a list of plots, passes back adjusted list of plots
adjust_plots_shared_ylimits <- function(plotList) {
  #read limits
  first <- TRUE
  for (plot in plotList) {
    if (first) {
      nlimits <- get_plot_view_ylimits(plot)
      first <- FALSE
    } else {
      altLimits <- get_plot_view_ylimits(plot)
      nlimits$ymin <- min(nlimits$ymin,altLimits$ymin)
      nlimits$ymax <- max(nlimits$ymax,altLimits$ymax)
    }
  }
  message(paste("new limits are:",nlimits$ymin,nlimits$ymax))
  #adjust limits
  lapply(plotList,change_plot_ylimits,nlimits)
}

I thought this might also be useful for others.


There is one problem, perhaps someone knows how to deal with: The ranges reported are "big enough" to include all the ranges from the plots in the list, but they are a lot bigger than the actual maximum (say, in a list of plots using stat_smooth( method = "lm")
M
Maximilian

This is a potential work around for you! This works unless you change the axis limits in the layout of the plot. It essentially takes the range from the data in the plot, so it work better when the axis is changed through filtering data rather than by using the layout function.

Here's the code!

# load ggplot2
library(ggplot2)

# A basic scatterplot
p <-ggplot(iris, aes(x=Sepal.Length, y=Sepal.Width, color=Species)) + 
      geom_point(size=6)

# p$data returns the dataset used to create the plot (iris)
head(p$data)

# Choose plot variable you want range for 
range(p$data[,"Sepal.Length"]) # * c(0.95, 1.05)

Its not a perfect solution but is a great easy quick workaround, hope it helped!


n
needshelp

Update:

ggplot2 version 3.3.2 now uses this code:

xmin <- ggplot_build(myPlot)$layout$panel_params[[1]]$x_range[1]
xmax <- ggplot_build(myPlot)$layout$panel_params[[1]]$x_range[2]