如何提取 ggplot2对象的绘图轴范围?

我有一个来自 ggplot2的对象,比如说 myPlot,我如何识别 x 轴和 y 轴的范围?

它似乎不是数据值范围的简单倍数,因为可以重新缩放图形,修改轴的范围,等等。除了如何设置坐标轴的范围外,findFn(来自 sos)和谷歌似乎没有显示出相关的结果。

38782 次浏览

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

Get the yrange with

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

and the xrange with

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

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

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

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...

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

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.

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!

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]