Jak mogę wyodrębnić zakresy osi wykresu dla obiektu ggplot2?

88

Mam obiekt z ggplot2, powiedzmy myPlot, jak mogę zidentyfikować zakresy dla osi X i Y?

Wydaje się, że nie jest to zwykła wielokrotność zakresu wartości danych, ponieważ można przeskalować wykresy, zmodyfikować zakresy osi i tak dalej. findFn(from sos) i Google nie wydają się zwracać odpowiednich wyników, poza tym, jak ustawić zakresy osi.

Iterator
źródło
1
Jestem prawie pewien, że nie można tego wyodrębnić bezpośrednio z samego obiektu wykresu, ale można to wywnioskować (w prostych przypadkach) na podstawie danych i wartości domyślnych dla expand. Zobacz tutaj .
joran
1
Odniosłem się do expandargumentu scale_*funkcji w ggplot. Na przykład zobacz wymienione tutaj wartości domyślne .
joran
6
Będziesz mógł go wyodrębnić w następnej wersji ...
hadley
1
Czy mógłbyś zamiast tego przyjąć odpowiedź Alexa Holcombe? Paul Hiemstra ma znaczenie tylko dla wersji ggplot2 sprzed ponad trzech lat.
Max Ghenis
4
** Od sierpnia 2018 r. Można wyodrębnić zakresy osi x i y za pomocą następującego wzoru. ** ggplot_build(obj)$layout$panel_scales_x[[1]]$range$range ggplot_build(obj)$layout$panel_scales_y[[1]]$range$range
Michael

Odpowiedzi:

41

W nowszych wersjach ggplot2 informacje te można znaleźć w wynikach polecenia ggplot_build(p), gdzie pjest twój obiekt ggplot.

W przypadku starszych wersji ggplot (<0.8.9) działa następujące rozwiązanie:

Może to być pomocne, dopóki Hadley nie wyda nowej wersji. Jeśli nie ustawisz granic w wykresie, w obiekcie ggplot nie będzie żadnych informacji. Jednak w takim przypadku możesz użyć wartości domyślnych ggplot2 i pobrać xlim i ylim z danych.

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

$x
NULL

$y
NULL

Po ustawieniu granic stają się one dostępne w obiekcie:

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

$y
NULL
Paul Hiemstra
źródło
34
W szczególności w nowszych wersjach ggplot2 można uzyskać wartość yrange za pomocą ggplot_build (ggobj) $ panel $ range [[1]] $ y.range i xrange za pomocą ggplot_build (ggobj) $ panel $ range [[1]] $ x.range
Alex Holcombe
11
Dla ggplot2wersji 2.1.0.9001 użyj tego Rkodu: ggplot_build(obj)$layout$panel_ranges[[1]]$x.range ggplot_build(obj)$layout$panel_ranges[[1]]$y.range
GegznaV
18
Dla ggplot2 wersji 2.2.1.9000 i (najprawdopodobniej) nowszych użyj tego Rkodu: ggplot_build(obj)$layout$panel_scales_x[[1]]$range$range ggplot_build(obj)$layout$panel_scales_y[[1]]$range$range
GegznaV
3
Czy nie ma sposobu, aby zrobić to dynamicznie w pierwotnym wywołaniu fabuły?
jzadra
4
W 2.2.1 możesz także użyć layer_scales (ggobj) $ y $ range $ range
Alex Holcombe
40

Używam ggplot2wersji 2, nie jestem pewien, czy to jest ta sama wersja, co poprzednia. Załóżmy, że zapisałeś swój wykres na pltobiekcie. Wyodrębnienie zakresów jest łatwe,

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

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

W przypadku wykresu fasetek można uzyskać dostęp do skal poszczególnych aspektów za pomocą layer_scales(plot, row_idx, col_idx). Na przykład, aby uzyskać dostęp do aspektu w pierwszym wierszu i drugiej kolumnie,

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

# x-range
layer_scales(plt, 1, 2)$x$range$range
TheRimalaya
źródło
2
I wersja 3.1.0
r_alanb,
2
Zauważ, że daje to zakres danych do wykreślenia - aby uzyskać pełny zakres osi, musisz zezwolić na rozszerzenie skali. Ponadto, jeśli limity zostały ustalone (np. Przez ylimlub coord_cartesian), rozszerzenie skali zostanie zastosowane do tych limitów, a nie do tych zwróconych przez kod podany tutaj.
Heather Turner
22

AKTUALIZACJA z listopada 2018 r

Od ggplot2 wersji 3.1.0 działa:

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

Wygodna funkcja:

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)

Do następnej aktualizacji ...

GegznaV
źródło
1
Zaproponowano edycję z wygodną funkcją, cofnij, jeśli ci się nie podoba. ;-)
PatrickT
1
@PatrickT Twoja aktualizacja jest naprawdę wygodna. Naprawdę to doceniam :)
GegznaV
20

Zdobądź yrange z

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

a xzakres z

ggplot_build(myPlot)$panel$ranges[[1]]$x.range
Alex Holcombe
źródło
2
Te rozwiązania działają dobrze w przypadku ciągłych osi numerycznych, ale jak można obsługiwać osie z datami (skala ciągła) lub wartościami jakościowymi? Kiedy używam tej metody, otrzymuję duże wartości liczbowe, które wymagają konwersji do formatu daty, aby dodać tekst za pomocą geom_text.
Joseph Kreke,
Co się stanie, jeśli nie ustawiam limitów osi, ale używam tego, co domyślnie sugeruje ggplot? Mój przypadek użycia jest taki, że podoba mi się domyślne wartości dla wykresu 1, ale chcę, aby wykres 2 miał takie same granice osi jak wykres 1.
NewNameStat
16

W wersji 2.2.0 należy to zrobić w następujący sposób:

# y-range
ggplot_build(plot.object)$layout$panel_ranges[[1]]$y.range
# x-range
ggplot_build(plot.object)$layout$panel_ranges[[1]]$x.range
pat-s
źródło
8

Począwszy od sierpnia 2018 r., Wyodrębniasz zakresy osi x i y w następujący sposób.

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

Michał
źródło
2

Jak wspomniano tutaj: https://gist.github.com/tomhopper/9076152#gistcomment-2624958 istnieje różnica między tymi dwiema opcjami:

#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

Oto zestaw wygodnych funkcji do pobrania listy wykresów, wyodrębnienia wspólnego zakresu osi Y i zastąpienia go. Potrzebowałem tego, ponieważ użyłem różnych zestawów danych w ramach jednego wykresu uporządkowanego za pomocą 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)
}

Pomyślałem, że może to być przydatne również dla innych.

Frederik
źródło
Jest jeden problem, być może ktoś wie, jak sobie z nim radzić: zgłaszane zakresy są „wystarczająco duże”, aby objąć wszystkie zakresy z działek na liście, ale są znacznie większe niż rzeczywiste maksimum (powiedzmy na liście działki przy użyciustat_smooth( method = "lm")
Frederik