¿Qué hacen hjust y vjust al hacer un diagrama usando ggplot?


159

Cada vez que hago un diagrama usando ggplot, paso un poco de tiempo probando diferentes valores para hjust y vjust en una línea como

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

para que las etiquetas del eje se alineen donde las etiquetas del eje casi tocan el eje y están alineadas contra él (justificadas por el eje, por así decirlo). Sin embargo, realmente no entiendo lo que está pasando. A menudo, hjust = 0.5ofrece resultados tan drásticamente diferentes de hjust = 0.6, por ejemplo, que no he podido resolverlo solo jugando con diferentes valores.

¿Alguien puede señalarme una explicación completa de cómo funcionan las opciones hjust y vjust?


1
Di un ejemplo específico, en los comentarios a la primera respuesta. Aparentemente, el uso de números fuera de 0-1 no está definido, lo que, si no explica por qué hjust = -1 tiene un comportamiento extraño, al menos explica que es de esperar que sea extraño.
William Gunn

Respuestas:


277

El valor de hjusty vjustsolo se define entre 0 y 1:

  • 0 significa justificado a la izquierda
  • 1 significa justificado a la derecha

Fuente: ggplot2, Hadley Wickham, página 196

(Sí, sé que en la mayoría de los casos puede usarlo más allá de este rango, pero no espere que se comporte de una manera específica. Esto está fuera de las especificaciones).

hjustcontrola la justificación horizontal y vjustcontrola la justificación vertical.

Un ejemplo debería aclarar esto:

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))

ingrese la descripción de la imagen aquí


Para comprender lo que sucede cuando cambia el hjusttexto en el eje, debe comprender que la alineación horizontal para el texto del eje se define no en relación con el eje x, sino con todo el diagrama (donde esto incluye el texto del eje y). (Esto es, en mi opinión, desafortunado. Sería mucho más útil tener la alineación relativa al eje).

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)

ingrese la descripción de la imagen aquí


Para explorar lo que sucede con la vjustalineación de las etiquetas de los ejes:

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)

ingrese la descripción de la imagen aquí


1
Entonces, para el caso de ángulo = 45, cuando tengo etiquetas de eje de longitud variable, digamos de 25 a 5 caracteres, no están alineadas ni justificadas a la derecha ni a la izquierda de los límites de las palabras. Eche un vistazo a los ejes aquí. Si tuviera que usar angle = 45, ¿cómo los justificaría a la derecha y los alinearía contra el eje?
William Gunn

He intentado eso, y me sale Error in grid.Call("L_textBounds", as.graphicsAnnot(x$label), x$x, x$y, : Polygon edge not found (zero-width or zero-height?)por vjust = .72y superior.
William Gunn

1
@WilliamGunn Le sugiero que publique una nueva pregunta con su código.
Andrie

1
dado que opt está en desuso, ¿cómo ajustamos la posición del título del eje?
Cyrus Mohammadian

1
@CyrusMohammadian, he editado esta respuesta para que funcione con la sintaxis ggplot2 actual.
Gotita

16

Probablemente la más definitiva sea la Figura B.1 (d) del libro ggplot2, cuyos apéndices están disponibles en http://ggplot2.org/book/appendices.pdf .

ingrese la descripción de la imagen aquí

Sin embargo, no es tan simple. hjusty vjustcomo se describe hay cómo funciona geom_texty theme_text(a veces). Una forma de pensarlo es pensar en un cuadro alrededor del texto, y donde el punto de referencia está en relación con ese cuadro, en unidades relativas al tamaño del cuadro (y, por lo tanto, diferente para textos de diferente tamaño). Un hjust0.5 y un vjust0.5 centran el recuadro en el punto de referencia. La reducción hjustmueve la caja a la derecha en una cantidad de veces el ancho de la caja 0.5-hjust. Así hjust=0, cuando , el borde izquierdo de la caja está en el punto de referencia. Al aumentar, se hjustmueve la caja hacia la izquierda una cantidad de veces el ancho de la caja hjust-0.5. Cuandohjust=1, el cuadro se mueve la mitad del ancho del cuadro hacia la izquierda desde el centro, lo que coloca el borde derecho en el punto de referencia. Si hjust=2, el borde derecho de la caja es un ancho de caja a la izquierda del punto de referencia (el centro es el 2-0.5=1.5ancho de la caja a la izquierda del punto de referencia. Para vertical, menos está arriba y más está abajo. Esto es efectivamente lo que esa figura B.1 (d ) dice, pero extrapola más allá de [0,1].

Pero, a veces esto no funciona. Por ejemplo

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))

Las tres últimas tramas son idénticas. No sé por qué es eso. Además, si el texto se gira, entonces es más complicado. Considerar

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))

El primero tiene las etiquetas a la izquierda justificadas (en la parte inferior), el segundo las tiene centradas en algún recuadro para que sus centros se alineen, y el tercero las justifica a la derecha (para que sus lados derechos se alineen al lado del eje). El último, bueno, no puedo explicarlo de manera coherente. Tiene algo que ver con el tamaño del texto, el tamaño del texto más ancho, y no estoy seguro de qué más.


Muchas gracias por esto, esto ayuda para el caso donde angle = 90, pero lo que no entiendo es por qué la justificación correcta de las etiquetas ya no funciona cuando en lugar de angle = 90, uso angle = 45. Entiendo el comportamiento de angle = 45, hjust = 0, pero angle = 45, hjust = -1 es simplemente extraño.
William Gunn

Su primer ejemplo, de hecho, funciona. La razón por la que cree que no funciona es porque todas sus etiquetas tienen la misma altura. Inténtalo de nuevo con DF <- data.frame(x=c("a\na","b","cdefghijk","l"),y=1:4), es decir, con un \nsalto de línea en uno de los títulos.
Andrie

@William, creo que @Andrie tiene razón; hjusty vjustsolo se definen entre 0 y 1; El comportamiento fuera de ese rango no tiene por qué tener sentido.
Brian Diggs

@ Andrew, tienes razón. Pero todavía me cuesta hacer un modelo mental coherente en el caso del título / texto del eje. Para el texto del eje, hjust=0alinea el borde izquierdo con el tic; hjust=0.5se centra en el tic; hjust=1alinea el borde derecho con el tic (cuadro en movimiento relativo al punto de referencia). Pero se vjustalinea dentro de un cuadro del tamaño de la etiqueta más alta.
Brian Diggs

@BrianDiggs En el caso de las vjustetiquetas de eje, todas las etiquetas se alinean simultáneamente entre sí. Por lo tanto, todos los bordes superiores se alinean cuando vjust=1y del mismo modo todos los bordes inferiores cuando vjust=0. Esto tiene sentido para mi.
Andrie
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.