Comment extraire les plages des axes de tracé pour un objet ggplot2?

87

J'ai un objet ggplot2, disons myPlot, comment puis-je identifier les plages pour les axes x et y?

Cela ne semble pas être un simple multiple de la plage des valeurs de données, car on peut redimensionner les tracés, modifier les plages des axes, etc. findFn(from sos) et Google ne semblent pas donner de résultats pertinents, à part la manière de définir les plages des axes.

Itérateur
la source
1
Je suis assez sûr que cela ne peut pas être extrait directement de l'objet de tracé lui-même, mais vous pouvez le déduire (dans des cas simples) de vos données et des valeurs par défaut pour expand. Regardez ici .
joran
1
Je faisais référence à l' expandargument des scale_*fonctions dans ggplot. Par exemple, consultez les valeurs par défaut répertoriées ici .
joran
6
Vous pourrez l'extraire dans la prochaine version ...
hadley
1
Pourriez-vous accepter la réponse d'Alex Holcombe à la place? Celui de Paul Hiemstra n'est pertinent que pour les versions de ggplot2 d'il y a plus de trois ans.
Max Ghenis
3
** Depuis août 2018, vous extrayez les plages des axes x et y avec les éléments suivants. ** ggplot_build(obj)$layout$panel_scales_x[[1]]$range$range ggplot_build(obj)$layout$panel_scales_y[[1]]$range$range
Michael

Réponses:

41

Dans les versions plus récentes de ggplot2, vous pouvez trouver ces informations dans la sortie de ggplot_build(p), où se ptrouve votre objet ggplot.

Pour les anciennes versions de ggplot (<0.8.9), la solution suivante fonctionne:

Et jusqu'à ce que Hadley publie la nouvelle version, cela pourrait être utile. Si vous ne définissez pas les limites dans le tracé, il n'y aura aucune information dans l'objet ggplot. Cependant, dans ce cas, vous pouvez utiliser les valeurs par défaut de ggplot2 et obtenir les xlim et ylim à partir des données.

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

$x
NULL

$y
NULL

Une fois que vous avez défini les limites, elles deviennent disponibles dans l'objet:

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

$y
NULL
Paul Hiemstra
la source
34
Plus précisément, dans les versions plus récentes de ggplot2, vous pouvez obtenir le yrange avec ggplot_build (ggobj) $ panel $ ranges [[1]] $ y.range et le xrange avec ggplot_build (ggobj) $ panel $ ranges [[1]] $ x.range
Alex Holcombe
11
Pour la ggplot2version 2.1.0.9001, utilisez ce Rcode: ggplot_build(obj)$layout$panel_ranges[[1]]$x.range ggplot_build(obj)$layout$panel_ranges[[1]]$y.range
GegznaV
17
Pour la ggplot2 version 2.2.1.9000 et (très probablement) plus récente, utilisez ce Rcode: ggplot_build(obj)$layout$panel_scales_x[[1]]$range$range ggplot_build(obj)$layout$panel_scales_y[[1]]$range$range
GegznaV
3
N'y a-t-il aucun moyen de le faire de manière dynamique dans l'appel de l'intrigue d'origine?
jzadra
4
Dans 2.2.1, vous pouvez également utiliser layer_scales (ggobj) $ y $ range $ range
Alex Holcombe
40

J'utilise la ggplot2version 2, je ne sais pas s'il s'agit de la version précédente, supposons que vous ayez enregistré votre tracé sur l' pltobjet. Il est facile d'extraire les gammes,

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

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

En cas de tracé de facettes, vous pouvez accéder aux échelles des facettes individuelles à l'aide de layer_scales(plot, row_idx, col_idx). Par exemple pour accéder à la facette de la première ligne et de la deuxième colonne,

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

# x-range
layer_scales(plt, 1, 2)$x$range$range
TheRimalaya
la source
2
Et version 3.1.0
r_alanb
2
Notez que cela vous donne la plage des données à tracer - pour obtenir la plage d'axe complète, vous devrez permettre l'expansion de l'échelle. De plus, si des limites ont été fixées (par exemple via ylimou coord_cartesian), l'expansion d'échelle sera appliquée à ces limites plutôt qu'à celles renvoyées par le code donné ici.
Heather Turner
22

MISE À JOUR novembre 2018

À partir de la ggplot2 version 3.1.0 , les éléments suivants fonctionnent:

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

Une fonction de confort:

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)

Jusqu'à la prochaine mise à jour ...

GegznaV
la source
1
Suggéré une modification avec une fonction pratique, revenir en arrière si vous ne l'aimez pas. ;-)
PatrickT
1
@PatrickT votre mise à jour est vraiment pratique. Je l'apprécie vraiment :)
GegznaV
20

Obtenez le yrange avec

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

et le xrange avec

ggplot_build(myPlot)$panel$ranges[[1]]$x.range
Alex Holcombe
la source
2
Ces solutions fonctionnent bien pour les axes numériques continus, mais comment gérer les axes avec des dates (échelle continue) ou des valeurs catégorielles? Lorsque j'utilise cette méthode, j'obtiens de grandes valeurs numériques qui nécessitent une conversion au format de date afin d'ajouter du texte à l'aide de geom_text.
Joseph Kreke
Que faire si je ne définis pas les limites de l'axe mais que j'utilise ce que ggplot suggère par défaut? Mon cas d'utilisation est que j'aime les valeurs par défaut du tracé 1, mais je veux que le tracé 2 ait les mêmes limites d'axe que le tracé 1.
NewNameStat
16

Dans la version 2.2.0, cela doit être fait comme suit:

# 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
la source
8

Depuis août 2018, vous extrayez les plages des axes x et y avec les éléments suivants.

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

Michael
la source
2

Comme mentionné ici: https://gist.github.com/tomhopper/9076152#gistcomment-2624958 il y a une différence entre les deux 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

Voici un ensemble de fonctions pratiques pour prendre une liste de tracés, extraire la plage commune de l'axe y et la remplacer. J'en avais besoin parce que j'ai utilisé différents ensembles de données dans un graphique organisé 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)
}

J'ai pensé que cela pourrait également être utile pour d'autres.

Frederik
la source
Il y a un problème, peut-être que quelqu'un sait comment s'y prendre: les plages signalées sont "suffisamment grandes" pour inclure toutes les plages des parcelles de la liste, mais elles sont beaucoup plus grandes que le maximum réel (par exemple, dans une liste de parcelles utilisantstat_smooth( method = "lm")
Frederik