Как я могу извлечь диапазоны осей графика для объекта ggplot2?

88

У меня есть объект ggplot2, скажем myPlot, как я могу определить диапазоны для осей x и y?

Это не похоже на простое кратное диапазону значений данных, потому что можно масштабировать графики, изменять диапазоны осей и так далее. findFn(from sos) и Google, похоже, не дают релевантных результатов, кроме как установить диапазоны осей.

Итератор
источник
1
Я почти уверен, что его нельзя извлечь непосредственно из самого объекта графика, но вы можете вывести его (в простых случаях) из ваших данных и значений по умолчанию для expand. Смотрите здесь .
Joran
1
Я имел в виду expandаргумент scale_*функций в ggplot. Например, см. Перечисленные здесь значения по умолчанию .
Joran
6
Вы сможете извлечь его в следующей версии ...
Хадли
1
Не могли бы вы вместо этого принять ответ Алекса Холкомба? Пол Хиемстры актуален только для версий ggplot2, выпущенных более трех лет назад.
Макс Генис
4
** По состоянию на август 2018 года вы извлекаете диапазоны осей x и y следующим образом. ** ggplot_build(obj)$layout$panel_scales_x[[1]]$range$range ggplot_build(obj)$layout$panel_scales_y[[1]]$range$range
Майкл

Ответы:

41

В более новых версиях ggplot2 вы можете найти эту информацию среди выходных данных ggplot_build(p), где pнаходится ваш объект ggplot.

Для более старых версий ggplot (<0.8.9) работает следующее решение:

И пока Хэдли не выпустит новую версию, это может быть полезно. Если вы не установите ограничения на графике, в объекте ggplot не будет информации. Однако в этом случае вы можете использовать значения по умолчанию для ggplot2 и получить xlim и ylim из данных.

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

$x
NULL

$y
NULL

Как только вы установите лимиты, они станут доступны в объекте:

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

$y
NULL
Пол Хиемстра
источник
34
В частности, в более новых версиях ggplot2 вы можете получить yrange с помощью ggplot_build (ggobj) $ panel $ range [[1]] $ y.range и xrange с помощью ggplot_build (ggobj) $ panel $ range [[1]] $ x.range
Алекс Холкомб
11
Для ggplot2версии 2.1.0.9001 используйте этот Rкод: ggplot_build(obj)$layout$panel_ranges[[1]]$x.range ggplot_build(obj)$layout$panel_ranges[[1]]$y.range
GegznaV
18
Для ggplot2 версии 2.2.1.9000 и (скорее всего) более новой используйте этот Rкод: ggplot_build(obj)$layout$panel_scales_x[[1]]$range$range ggplot_build(obj)$layout$panel_scales_y[[1]]$range$range
GegznaV
3
Нет ли способа сделать это динамически в исходном вызове сюжета?
jzadra
4
В 2.2.1 вы также можете использовать layer_scales (ggobj) $ y $ range $ range
Алекс Холкомб
40

Я использую ggplot2версию 2, я не уверен, совпадает ли она с предыдущей версией. Предположим, вы сохранили свой график на pltобъекте. Диапазоны легко извлечь,

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

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

В случае построения фасетов вы можете получить доступ к шкалам отдельных фасетов, используя layer_scales(plot, row_idx, col_idx). Например, чтобы получить доступ к фасету в первой строке и втором столбце,

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

# x-range
layer_scales(plt, 1, 2)$x$range$range
TheRimalaya
источник
2
И версия 3.1.0
r_alanb
2
Обратите внимание, что это дает вам диапазон данных, которые должны быть нанесены на график - чтобы получить полный диапазон оси, вам нужно будет учесть расширение шкалы. Более того, если пределы были установлены (например, с помощью ylimили coord_cartesian), расширение шкалы будет применяться к этим пределам, а не к тем, которые возвращаются приведенным здесь кодом.
Хизер Тернер
22

Ноябрь 2018 ОБНОВЛЕНИЕ

Начиная с ggplot2 версии 3.1.0 , работает следующее:

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

Удобная функция:

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)

До следующего обновления ...

ГегзнаВ
источник
1
Предложил правку с удобной функцией, откатывайтесь, если она вам не нравится. ;-)
PatrickT
1
@PatrickT ваше обновление действительно удобно. Я очень ценю это :)
GegznaV
20

Получите диапазон с

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

и xrange с

ggplot_build(myPlot)$panel$ranges[[1]]$x.range
Алекс Холкомб
источник
2
Эти решения хорошо работают для непрерывных числовых осей, но как можно обрабатывать оси с датами (непрерывная шкала) или категориальными значениями? Когда я использую этот метод, я получаю большие числовые значения, которые требуют некоторого преобразования в формат даты, чтобы добавить текст с помощью geom_text.
Джозеф Креке,
Что делать, если я не устанавливаю пределы оси, а использую то, что предлагает ggplot по умолчанию? В моем случае мне нравятся значения по умолчанию для графика 1, но я хочу, чтобы график 2 имел те же пределы оси, что и график 1.
NewNameStat
16

В версии 2.2.0 это нужно сделать следующим образом:

# y-range
ggplot_build(plot.object)$layout$panel_ranges[[1]]$y.range
# x-range
ggplot_build(plot.object)$layout$panel_ranges[[1]]$x.range
погладить
источник
8

По состоянию на август 2018 вы извлекаете диапазоны осей x и y следующим образом.

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

Майкл
источник
2

Как уже упоминалось здесь: https://gist.github.com/tomhopper/9076152#gistcomment-2624958, есть разница между двумя вариантами:

#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

Вот набор удобных функций для получения списка графиков, извлечения общего диапазона оси Y и его замены. Мне это было нужно, потому что я использовал разные наборы данных в одном графике, организованном с помощью 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)
}

Я подумал, что это может быть полезно и другим.

Фредерик
источник
Есть одна проблема, с которой, возможно, кто-то знает, как бороться: указанные диапазоны «достаточно велики», чтобы включать все диапазоны из графиков в списке, но они намного больше фактического максимума (скажем, в списке участки с использованиемstat_smooth( method = "lm")
Фредерик