Como posso extrair os intervalos dos eixos do gráfico para um objeto ggplot2?

87

Tenho um objeto de ggplot2, digamos myPlot, como posso identificar os intervalos dos eixos xey?

Não parece ser um simples múltiplo do intervalo dos valores dos dados, porque é possível redimensionar os gráficos, modificar os intervalos dos eixos e assim por diante. findFn(de sos) e o Google não parecem estar apresentando resultados relevantes, além de como definir os intervalos dos eixos.

Iterator
fonte
1
Tenho quase certeza de que não pode ser extraído diretamente do próprio objeto de plotagem, mas você pode inferir (em casos simples) a partir de seus dados e dos valores padrão de expand. Veja aqui .
joran,
1
Eu estava me referindo ao expandargumento das scale_*funções em ggplot. Por exemplo, consulte os padrões listados aqui .
joran,
6
Você será capaz de extraí-lo na próxima versão ...
hadley
1
Você poderia aceitar a resposta de Alex Holcombe em vez disso? Paul Hiemstra só é relevante para versões do ggplot2 de mais de três anos atrás.
Max Ghenis
3
** A partir de agosto de 2018, você extraiu os intervalos dos eixos xey com o seguinte. ** ggplot_build(obj)$layout$panel_scales_x[[1]]$range$range ggplot_build(obj)$layout$panel_scales_y[[1]]$range$range
Michael,

Respostas:

41

Em versões mais recentes do ggplot2, você pode encontrar essas informações entre a saída de ggplot_build(p), onde pestá seu objeto ggplot.

Para versões mais antigas do ggplot (<0.8.9), a seguinte solução funciona:

E até que Hadley lance a nova versão, isso pode ser útil. Se você não definir os limites no gráfico, não haverá informações no objeto ggplot. No entanto, nesse caso, você pode usar os padrões de ggplot2 e obter xlim e ylim dos dados.

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

$x
NULL

$y
NULL

Depois de definir os limites, eles se tornam disponíveis no objeto:

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

$y
NULL
Paul Hiemstra
fonte
34
Especificamente, nas versões mais recentes do ggplot2, você pode obter o yrange com ggplot_build (ggobj) $ panel $ ranges [[1]] $ y.range e o xrange com ggplot_build (ggobj) $ panel $ ranges [[1]] $ x.range
Alex Holcombe
11
Para a ggplot2versão 2.1.0.9001, use este Rcódigo: ggplot_build(obj)$layout$panel_ranges[[1]]$x.range ggplot_build(obj)$layout$panel_ranges[[1]]$y.range
GegznaV
17
Para a ggplot2 versão 2.2.1.9000 e (provavelmente) mais recente, use este Rcódigo: ggplot_build(obj)$layout$panel_scales_x[[1]]$range$range ggplot_build(obj)$layout$panel_scales_y[[1]]$range$range
GegznaV
3
Não há como fazer isso dinamicamente dentro da chamada do enredo original?
jzadra
4
No 2.2.1, você também pode usar layer_scales (ggobj) $ y $ range $ range
Alex Holcombe
40

Estou usando a ggplot2versão 2, não tenho certeza se é a mesma da versão anterior, suponha que você salvou seu gráfico no pltobjeto. É fácil extrair os intervalos,

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

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

No caso do gráfico de facetas, você pode acessar escalas de facetas individuais usando layer_scales(plot, row_idx, col_idx). Por exemplo, para acessar a faceta na primeira linha e na segunda coluna,

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

# x-range
layer_scales(plt, 1, 2)$x$range$range
TheRimalaya
fonte
2
E versão 3.1.0
r_alanb
2
Observe que isso fornece a faixa dos dados a serem plotados - para obter a faixa total do eixo, você precisará permitir a expansão da escala. Além disso, se os limites foram definidos (por exemplo, via ylimou coord_cartesian), a expansão da escala será aplicada a esses limites, em vez daqueles retornados pelo código fornecido aqui.
Heather Turner
22

ATUALIZAÇÃO DE novembro de 2018

A partir da ggplot2 versão 3.1.0 , funciona o seguinte:

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

Uma função de conveniência:

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)

Até a próxima atualização ...

GegznaV
fonte
1
Sugeriu uma edição com uma função de conveniência, retroceda se não gostar. ;-)
PatrickT
1
@PatrickT sua atualização é realmente conveniente. Agradeço muito :)
GegznaV
20

Obtenha o yrange com

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

e o xrange com

ggplot_build(myPlot)$panel$ranges[[1]]$x.range
Alex Holcombe
fonte
2
Essas soluções funcionam bem para eixos numéricos contínuos, mas como lidar com eixos com datas (escala contínua) ou valores categóricos? Quando eu uso este método, obtenho grandes valores numéricos que requerem alguma conversão para o formato de data para adicionar texto usando geom_text.
Joseph Kreke
E se eu não estiver definindo os limites do eixo, mas usando o que o ggplot sugere por padrão? Meu caso de uso é que gosto dos valores padrão para o gráfico 1, mas quero que o gráfico 2 tenha os mesmos limites de eixo que o gráfico 1.
NewNameStat
16

Na versão 2.2.0, isso deve ser feito da seguinte forma:

# 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
fonte
8

A partir de agosto de 2018, você extraiu os intervalos dos eixos xey com o seguinte.

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

Michael
fonte
2

Conforme mencionado aqui: https://gist.github.com/tomhopper/9076152#gistcomment-2624958 há uma diferença entre as duas opções:

#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

Aqui está um conjunto de funções convenientes para obter uma lista de gráficos, extrair o intervalo comum do eixo y e substituí-lo. Eu precisava disso porque usei diferentes conjuntos de dados em um gráfico organizado por meio de 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)
}

Achei que isso também poderia ser útil para outras pessoas.

Frederik
fonte
Há um problema com o qual talvez alguém saiba como lidar: os intervalos relatados são "grandes o suficiente" para incluir todos os intervalos dos gráficos na lista, mas são muito maiores do que o máximo real (digamos, em uma lista de plotagens usandostat_smooth( method = "lm")
Frederik