Que font hjust et vjust lors de la création d'un graphique à l'aide de ggplot?

159

Chaque fois que je fais un tracé en utilisant ggplot, je passe un peu de temps à essayer différentes valeurs pour hjust et vjust dans une ligne comme

+ opts(axis.text.x = theme_text(hjust = 0.5))

pour que les étiquettes des axes s'alignent là où les étiquettes des axes touchent presque l'axe et sont alignées contre lui (justifiées par rapport à l'axe, pour ainsi dire). Cependant, je ne comprends pas vraiment ce qui se passe. Souvent, hjust = 0.5donne des résultats si radicalement différents hjust = 0.6, par exemple, que je n'ai pas été en mesure de le comprendre simplement en jouant avec des valeurs différentes.

Quelqu'un peut-il m'indiquer une explication complète du fonctionnement des options hjust et vjust?

William Gunn
la source
1
J'ai donné un exemple précis, dans les commentaires sur la première réponse. Apparemment, l'utilisation de nombres en dehors de 0-1 n'est pas définie, ce qui, si ce n'est d'expliquer pourquoi hjust = -1 a un comportement bizarre, explique au moins qu'il faut s'y attendre.
William Gunn

Réponses:

277

La valeur de hjustet vjustn'est définie qu'entre 0 et 1:

  • 0 signifie justifié à gauche
  • 1 signifie justifié à droite

Source: ggplot2, Hadley Wickham, page 196

(Oui, je sais que dans la plupart des cas, vous pouvez l'utiliser au-delà de cette plage, mais ne vous attendez pas à ce qu'il se comporte d'une manière spécifique. Ceci est en dehors des spécifications.)

hjustcontrôle la justification horizontale et vjustcontrôle la justification verticale.

Un exemple devrait clarifier cela:

td <- expand.grid(
    hjust=c(0, 0.5, 1),
    vjust=c(0, 0.5, 1),
    angle=c(0, 45, 90),
    text="text"
)

ggplot(td, aes(x=hjust, y=vjust)) + 
    geom_point() +
    geom_text(aes(label=text, angle=angle, hjust=hjust, vjust=vjust)) + 
    facet_grid(~angle) +
    scale_x_continuous(breaks=c(0, 0.5, 1), expand=c(0, 0.2)) +
    scale_y_continuous(breaks=c(0, 0.5, 1), expand=c(0, 0.2))

entrez la description de l'image ici


Pour comprendre ce qui se passe lorsque vous modifiez le hjusttexte de l'axe, vous devez comprendre que l'alignement horizontal du texte de l'axe n'est pas défini par rapport à l'axe des x, mais à l'ensemble du tracé (où cela inclut le texte de l'axe des y). (C'est, à mon avis, regrettable. Il serait beaucoup plus utile d'avoir l'alignement par rapport à l'axe.)

DF <- data.frame(x=LETTERS[1:3],y=1:3)
p <- ggplot(DF, aes(x,y)) + geom_point() + 
    ylab("Very long label for y") +
    theme(axis.title.y=element_text(angle=0))


p1 <- p + theme(axis.title.x=element_text(hjust=0)) + xlab("X-axis at hjust=0")
p2 <- p + theme(axis.title.x=element_text(hjust=0.5)) + xlab("X-axis at hjust=0.5")
p3 <- p + theme(axis.title.x=element_text(hjust=1)) + xlab("X-axis at hjust=1")

library(ggExtra)
align.plots(p1, p2, p3)

entrez la description de l'image ici


Pour explorer ce qui se passe avec l' vjustalignement des étiquettes d'axe:

DF <- data.frame(x=c("a\na","b","cdefghijk","l"),y=1:4)
p <- ggplot(DF, aes(x,y)) + geom_point()

p1 <- p + theme(axis.text.x=element_text(vjust=0, colour="red")) + 
        xlab("X-axis labels aligned with vjust=0")
p2 <- p + theme(axis.text.x=element_text(vjust=0.5, colour="red")) + 
        xlab("X-axis labels aligned with vjust=0.5")
p3 <- p + theme(axis.text.x=element_text(vjust=1, colour="red")) + 
        xlab("X-axis labels aligned with vjust=1")


library(ggExtra)
align.plots(p1, p2, p3)

entrez la description de l'image ici

Andrie
la source
1
Donc, pour le cas de l'angle = 45, lorsque j'ai des étiquettes d'axe de longueur variable, disons de 25 à 5 caractères, elles ne sont ni alignées ni justifiées à droite ou à gauche des limites du mot. Jetez un oeil aux axes ici Si je devais utiliser angle = 45, comment pourrais-je les rendre justifiés à droite et alignés contre l'axe?
William Gunn
J'ai essayé cela, et j'obtiens Error in grid.Call("L_textBounds", as.graphicsAnnot(x$label), x$x, x$y, : Polygon edge not found (zero-width or zero-height?)pour vjust = .72et plus.
William Gunn
1
@WilliamGunn Je vous suggère de poster une nouvelle question avec votre code.
Andrie
1
comme opt est obsolète, comment ajuster la position du titre de l'axe?
Cyrus Mohammadian
1
@CyrusMohammadian, j'ai édité cette réponse pour travailler avec la syntaxe actuelle de ggplot2.
Droplet
16

La plus définitive est probablement la Figure B.1 (d) du livre ggplot2, dont les annexes sont disponibles sur http://ggplot2.org/book/appendices.pdf .

entrez la description de l'image ici

Cependant, ce n’est pas aussi simple. hjustet vjustcomme décrit, il y a comment cela fonctionne dans geom_textet theme_text(parfois). Une façon d'y penser est de penser à une boîte autour du texte, et où se trouve le point de référence par rapport à cette boîte, en unités par rapport à la taille de la boîte (et donc différentes pour les textes de taille différente). Un hjustde 0,5 et un vjustde 0,5 centrent la boîte sur le point de référence. La réduction hjustdéplace la boîte vers la droite d'une quantité de fois la largeur de la boîte 0.5-hjust. Ainsi quand hjust=0, le bord gauche de la boîte est au point de référence. L'augmentation hjustdéplace la boîte vers la gauche d'une quantité de fois la largeur de la boîte hjust-0.5. Quandhjust=1, la boîte est déplacée d'une demi-largeur à gauche du centre, ce qui place le bord droit sur le point de référence. Si hjust=2, le bord droit de la boîte est une largeur de boîte à gauche du point de référence (le centre est la 2-0.5=1.5largeur de la boîte à gauche du point de référence. Pour la verticale, moins est en haut et plus est en bas. C'est effectivement ce que la Figure B.1 (d ) dit, mais il extrapole au-delà de [0,1].

Mais parfois cela ne fonctionne pas. Par exemple

DF <- data.frame(x=c("a","b","cdefghijk","l"),y=1:4)
p <- ggplot(DF, aes(x,y)) + geom_point()

p + opts(axis.text.x=theme_text(vjust=0))
p + opts(axis.text.x=theme_text(vjust=1))
p + opts(axis.text.x=theme_text(vjust=2))

Les trois derniers graphiques sont identiques. Je ne sais pas pourquoi. De plus, si le texte est pivoté, c'est plus compliqué. Considérer

p + opts(axis.text.x=theme_text(hjust=0, angle=90))
p + opts(axis.text.x=theme_text(hjust=0.5 angle=90))
p + opts(axis.text.x=theme_text(hjust=1, angle=90))
p + opts(axis.text.x=theme_text(hjust=2, angle=90))

Le premier a les étiquettes justifiées à gauche (contre le bas), le second les a centrées dans une boîte afin que leurs centres s'alignent, et le troisième les a justifiés à droite (de sorte que leurs côtés droits s'alignent à côté de l'axe). Le dernier, eh bien, je ne peux pas l'expliquer de manière cohérente. Cela a quelque chose à voir avec la taille du texte, la taille du texte le plus large, et je ne sais pas quoi d'autre.

Brian Diggs
la source
Merci beaucoup pour cela, cela aide dans le cas où angle = 90, mais ce que je ne comprends pas, c'est pourquoi la juste justification des étiquettes ne fonctionne plus alors qu'au lieu d'angle = 90, j'utilise angle = 45. Je comprends le comportement de l'angle = 45, hjust = 0, mais angle = 45, hjust = -1 est juste bizarre.
William Gunn
Votre premier exemple fonctionne, en fait. La raison pour laquelle vous pensez que cela ne fonctionne pas est que toutes vos étiquettes ont la même hauteur. Réessayez avec DF <- data.frame(x=c("a\na","b","cdefghijk","l"),y=1:4)- c'est-à-dire avec un \nsaut de ligne dans l'un des titres.
Andrie
@William, je pense que @Andrie a raison; hjustet vjustne sont définis qu'entre 0 et 1; un comportement en dehors de cette fourchette n’a pas de sens.
Brian Diggs
@Andrie, vous avez raison. Mais j'ai encore du mal à faire un modèle mental cohérent dans la casse titre / texte de l'axe. Pour le texte de l'axe, hjust=0aligne le bord gauche avec le tic; hjust=0.5se concentre sur le tic; hjust=1aligne le bord droit avec le tic (boîte mobile par rapport au point de référence). Mais vjusts'aligne dans une boîte de la taille de l'étiquette la plus haute.
Brian Diggs
@BrianDiggs Dans le cas des vjustétiquettes d'axe, toutes les étiquettes sont simultanément alignées les unes avec les autres. Ainsi, tous les bords supérieurs s'alignent quand vjust=1et de même tous les bords inférieurs quand vjust=0. Cela me semble parfaitement logique.
Andrie