Was machen hjust und vjust, wenn Sie mit ggplot einen Plot erstellen?

159

Jedes Mal, wenn ich mit ggplot einen Plot erstelle, verbringe ich ein wenig Zeit damit, verschiedene Werte für hjust und vjust in einer Zeile wie auszuprobieren

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

Damit die Achsenbeschriftungen dort ausgerichtet werden, wo die Achsenbeschriftungen fast die Achse berühren und bündig mit dieser sind (sozusagen auf die Achse ausgerichtet). Ich verstehe jedoch nicht wirklich, was los ist. Oft hjust = 0.5gibt es so dramatisch unterschiedliche Ergebnisse hjust = 0.6, zum Beispiel, dass ich es nicht herausfinden konnte, indem ich nur mit verschiedenen Werten herumspielte.

Kann mir jemand eine umfassende Erklärung geben, wie Hjust- und Vjust-Optionen funktionieren?

William Gunn
quelle
1
Ich habe in den Kommentaren zur ersten Antwort ein konkretes Beispiel gegeben. Anscheinend ist die Verwendung von Zahlen außerhalb von 0-1 undefiniert, was, wenn nicht erklärt wird, warum hjust = -1 bizarres Verhalten hat, zumindest erklärt, dass bizarr zu erwarten ist.
William Gunn

Antworten:

277

Der Wert von hjustund vjustwird nur zwischen 0 und 1 definiert:

  • 0 bedeutet linksbündig
  • 1 bedeutet rechtsbündig

Quelle: ggplot2, Hadley Wickham, Seite 196

(Ja, ich weiß, dass Sie es in den meisten Fällen außerhalb dieses Bereichs verwenden können, aber erwarten Sie nicht, dass es sich auf eine bestimmte Weise verhält. Dies liegt außerhalb der Spezifikation.)

hjuststeuert die horizontale Ausrichtung und vjustdie vertikale Ausrichtung.

Ein Beispiel sollte dies klarstellen:

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

Geben Sie hier die Bildbeschreibung ein


Um zu verstehen, was passiert, wenn Sie den hjustText in der Achse ändern , müssen Sie verstehen, dass die horizontale Ausrichtung für den Achsentext nicht in Bezug auf die x-Achse, sondern auf das gesamte Diagramm (einschließlich des Textes auf der y-Achse) definiert ist. (Dies ist meiner Ansicht nach unglücklich. Es wäre viel nützlicher, die Ausrichtung relativ zur Achse zu haben.)

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)

Geben Sie hier die Bildbeschreibung ein


So untersuchen Sie, was mit der vjustAusrichtung von Achsenbeschriftungen geschieht :

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)

Geben Sie hier die Bildbeschreibung ein

Andrie
quelle
1
Für den Fall von Winkel = 45, wenn ich Achsenbeschriftungen unterschiedlicher Länge habe, sagen wir 25 bis 5 Zeichen, sind sie weder rechts noch links von den Wortgrenzen ausgerichtet. Schauen Sie sich die Achsen hier an. Wenn ich Winkel = 45 verwenden würde, wie würde ich sie rechtsbündig und bündig mit der Achse machen?
William Gunn
Ich habe das versucht, und ich komme Error in grid.Call("L_textBounds", as.graphicsAnnot(x$label), x$x, x$y, : Polygon edge not found (zero-width or zero-height?)für vjust = .72und höher.
William Gunn
1
@WilliamGunn Ich schlage vor, Sie stellen eine neue Frage mit Ihrem Code.
Andrie
1
Wie passen wir die Position des Achsentitels an, da opt veraltet ist?
Cyrus Mohammadian
1
@CyrusMohammadian, ich habe diese Antwort bearbeitet, um mit der aktuellen ggplot2-Syntax zu arbeiten.
Tröpfchen
16

Am definitivsten ist wahrscheinlich Abbildung B.1 (d) des ggplot2-Buches, dessen Anhänge unter http://ggplot2.org/book/appendices.pdf verfügbar sind .

Geben Sie hier die Bildbeschreibung ein

Ganz so einfach ist es jedoch nicht. hjustund vjustwie beschrieben gibt es, wie es in geom_textund theme_text(manchmal) funktioniert . Eine Möglichkeit, sich das vorzustellen, besteht darin, sich ein Feld um den Text vorzustellen, bei dem sich der Bezugspunkt auf dieses Feld bezieht, und zwar in Einheiten relativ zur Größe des Feldes (und daher für Texte unterschiedlicher Größe unterschiedlich). Ein hjustWert von 0,5 und ein vjustWert von 0,5 zentrieren die Box auf dem Referenzpunkt. Durch Reduzieren wird hjustdie Box um einen Betrag der Boxbreite nach rechts verschoben 0.5-hjust. Wenn hjust=0sich also der linke Rand der Box am Referenzpunkt befindet. Durch Erhöhen wird hjustdie Box um einen Betrag der Boxbreite nach links verschoben hjust-0.5. Wannhjust=1wird die Box eine halbe Boxbreite von der Mitte nach links verschoben, wodurch die rechte Kante auf den Referenzpunkt gelegt wird. Wenn hjust=2der rechte Rand der Box eine Boxbreite links vom Referenzpunkt ist (Mitte sind die 2-0.5=1.5Boxbreiten links vom Referenzpunkt. Bei der Vertikalen ist weniger oben und mehr unten. Dies ist effektiv das, was in Abbildung B.1 (d ) sagt, aber es extrapoliert über [0,1] hinaus.

Aber manchmal funktioniert das nicht. Beispielsweise

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

Die drei letzteren Diagramme sind identisch. Ich weiß nicht warum das so ist. Wenn Text gedreht wird, ist dies auch komplizierter. Erwägen

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

Bei der ersten sind die Beschriftungen linksbündig (gegen den Boden) ausgerichtet, bei der zweiten sind sie in einem Feld zentriert, sodass ihre Mitten ausgerichtet sind, und bei der dritten sind sie rechtsbündig ausgerichtet (sodass ihre rechten Seiten neben der Achse ausgerichtet sind). Das letzte kann ich nicht kohärent erklären. Es hat etwas mit der Größe des Textes zu tun, der Größe des breitesten Textes, und ich bin mir nicht sicher, was noch.

Brian Diggs
quelle
Vielen Dank dafür, dies hilft für den Fall, dass Winkel = 90 ist, aber was ich nicht verstehe, ist, warum die richtige Ausrichtung von Etiketten nicht mehr funktioniert, wenn ich anstelle von Winkel = 90 Winkel = 45 verwende. Ich verstehe das Verhalten von Winkel = 45, Hjust = 0, aber Winkel = 45, Hjust = -1 ist nur bizarr.
William Gunn
Ihr erstes Beispiel funktioniert tatsächlich. Der Grund, warum Sie denken, dass es nicht funktioniert, ist, dass alle Ihre Etiketten die gleiche Höhe haben. Versuchen Sie es erneut mit DF <- data.frame(x=c("a\na","b","cdefghijk","l"),y=1:4)- dh mit einem \nZeilenumbruch in einem der Titel.
Andrie
@William, ich denke @Andrie hat es richtig; hjustund vjustsind nur zwischen 0 und 1 definiert; Verhalten außerhalb dieses Bereichs muss keinen Sinn ergeben.
Brian Diggs
@Andrie, du hast recht. Aber es fällt mir immer noch schwer, ein kohärentes mentales Modell im Achsentitel / Textfall zu erstellen. Für die Achse Text, hjust=0richtet die linke Kante mit dem tic; hjust=0.5zentriert sich auf den Tic; hjust=1Richtet die rechte Kante am Tic aus (Verschieben des Felds relativ zum Referenzpunkt). Aber vjustausrichtet innerhalb einer Box , die Größe des höchsten Label.
Brian Diggs
@BrianDiggs Bei vjustAchsenbeschriftungen werden alle Beschriftungen gleichzeitig zueinander ausgerichtet. So werden alle Oberkanten wann vjust=1und ebenso alle Unterkanten wann ausgerichtet vjust=0. Das macht für mich vollkommen Sinn.
Andrie