Co robią hjust i vjust podczas tworzenia fabuły za pomocą ggplot?

159

Za każdym razem, gdy tworzę wykres za pomocą ggplot, spędzam trochę czasu próbując różnych wartości hjust i vjust w linii takiej jak

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

aby etykiety osi były wyrównane w miejscu, w którym etykiety osi prawie dotykają osi i są zrównane z nią (wyrównane do osi, że tak powiem). Jednak tak naprawdę nie rozumiem, co się dzieje. Często hjust = 0.5daje tak radykalnie odmienne wyniki od hjust = 0.6, na przykład, że nie byłem w stanie tego rozgryźć, po prostu bawiąc się różnymi wartościami.

Czy ktoś może wskazać mi obszerne wyjaśnienie, jak działają opcje hjust i vjust?

William Gunn
źródło
1
Podałem konkretny przykład w komentarzach do pierwszej odpowiedzi. Najwyraźniej używanie liczb spoza zakresu 0-1 jest niezdefiniowane, co jeśli nie wyjaśnia, dlaczego hjust = -1 ma dziwne zachowanie, to przynajmniej wyjaśnia, że ​​dziwnego można się spodziewać.
William Gunn

Odpowiedzi:

277

Wartości hjusti vjustsą zdefiniowane tylko między 0 a 1:

  • 0 oznacza wyrównanie do lewej
  • 1 oznacza uzasadnione do prawej

Źródło: ggplot2, Hadley Wickham, strona 196

(Tak, wiem, że w większości przypadków można go używać poza tym zakresem, ale nie oczekuj, że będzie się zachowywał w jakikolwiek określony sposób. To jest poza specyfikacją).

hjuststeruje wyrównaniem poziomym i vjustwyrównaniem pionowym.

Przykład powinien to wyjaśnić:

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

wprowadź opis obrazu tutaj


Aby zrozumieć, co się dzieje, gdy zmieniasz hjusttekst na osi, musisz zrozumieć, że wyrównanie poziome tekstu osi jest definiowane nie w odniesieniu do osi x, ale do całego wykresu (gdzie obejmuje to tekst na osi y). (Moim zdaniem jest to niefortunne. O wiele bardziej przydatne byłoby ustawienie wyrównania względem osi).

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)

wprowadź opis obrazu tutaj


Aby zbadać, co dzieje się z vjustwyrównaniem etykiet osi:

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)

wprowadź opis obrazu tutaj

Andrie
źródło
1
Tak więc w przypadku kąta = 45, kiedy mam etykiety osi o różnej długości, powiedzmy od 25 do 5 znaków, nie są one wyrównane do prawej ani lewej strony granic słów. Spójrz na osie tutaj, gdybym użył kąta = 45, jak zrobiłbym je wyrównane do prawej i wyrównane z osią?
William Gunn
Próbowałem to i ja się Error in grid.Call("L_textBounds", as.graphicsAnnot(x$label), x$x, x$y, : Polygon edge not found (zero-width or zero-height?)do vjust = .72wyżej.
William Gunn
1
@WilliamGunn Proponuję zadać nowe pytanie ze swoim kodem.
Andrie,
1
ponieważ opcja opt jest przestarzała, w jaki sposób dostosowujemy pozycję tytułu osi?
Cyrus Mohammadio
1
@CyrusMohammadian, zredagowałem tę odpowiedź, aby pracować z bieżącą składnią ggplot2.
Droplet
16

Prawdopodobnie najbardziej ostateczny jest rysunek B.1 (d) książki ggplot2, której załączniki są dostępne pod adresem http://ggplot2.org/book/appendices.pdf .

wprowadź opis obrazu tutaj

Jednak nie jest to takie proste. hjusti vjustzgodnie z opisem, jak to działa w geom_texti theme_text(czasami). Jednym ze sposobów myślenia o tym jest myślenie o ramce wokół tekstu i miejscu, w którym punkt odniesienia znajduje się w stosunku do tego pola, w jednostkach zależnych od rozmiaru ramki (a zatem różne dla tekstów o różnych rozmiarach). Wartości hjust0,5 i vjust0,5 wyśrodkowują prostokąt w punkcie odniesienia. Zmniejszenie hjustprzesuwa pudełko w prawo o wielkość razy szerokość pudełka 0.5-hjust. Zatem kiedy hjust=0lewa krawędź pudełka znajduje się w punkcie odniesienia. Zwiększenie hjustprzesuwa ramkę w lewo o określoną wartość razy szerokość pudełka hjust-0.5. Kiedyhjust=1, pudełko zostanie przesunięte o pół szerokości pola w lewo od środka, co spowoduje umieszczenie prawej krawędzi w punkcie odniesienia. Jeśli hjust=2prawa krawędź prostokąta jest szerokością prostokąta na lewo od punktu odniesienia (środek to 2-0.5=1.5szerokość prostokąta na lewo od punktu odniesienia. W przypadku pionu mniej jest w górę, a więcej w dół. ) mówi, ale ekstrapoluje poza [0,1].

Ale czasami to nie działa. Na przykład

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

Trzy ostatnie wątki są identyczne. Nie wiem, dlaczego tak jest. Ponadto, jeśli tekst jest obracany, jest to bardziej skomplikowane. Rozważać

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

Pierwsza ma etykiety wyrównane do lewej (do dołu), druga ma je wyśrodkowane w jakimś polu, tak aby ich środki były wyrównane, a trzecia ma je wyrównane do prawej (tak, aby ich prawe boki były wyrównane do osi). Ostatniego, cóż, nie potrafię w spójny sposób wyjaśnić. Ma to coś wspólnego z rozmiarem tekstu, rozmiarem najszerszego tekstu i nie jestem pewien, co jeszcze.

Brian Diggs
źródło
Wielkie dzięki za to, to pomaga w przypadku, gdy kąt = 90, ale nie rozumiem, dlaczego wyrównanie etykiet do prawej już nie działa, gdy zamiast kąta = 90 używam kąta = 45. Rozumiem zachowanie angle = 45, hjust = 0, ale angle = 45, hjust = -1 jest po prostu dziwaczne.
William Gunn
W rzeczywistości Twój pierwszy przykład działa. Uważasz, że to nie działa, ponieważ wszystkie etykiety mają tę samą wysokość. Spróbuj ponownie z DF <- data.frame(x=c("a\na","b","cdefghijk","l"),y=1:4)- np. Z \nprzełamaniem wiersza w jednym z tytułów.
Andrie
@William, myślę, że @Andrie ma rację; hjusti vjustsą zdefiniowane tylko między 0 a 1; zachowanie poza tym zakresem nie musi mieć sensu.
Brian Diggs
@Andrie, masz rację. Ale nadal mam trudności z utworzeniem spójnego modelu mentalnego w przypadku tytułu / tekstu osi. W przypadku tekstu osi hjust=0wyrównuje lewą krawędź z kreską; hjust=0.5koncentruje się na tiku; hjust=1wyrównuje prawą krawędź z tikiem (przesuwanie prostokąta względem punktu odniesienia). Ale vjustwyrównuje się w polu wielkości najwyższej etykiety.
Brian Diggs
@BrianDiggs W przypadku vjustetykiet osi wszystkie etykiety są jednocześnie wyrównane względem siebie. Zatem wszystkie górne krawędzie są wyrównane, kiedy vjust=1i wszystkie dolne krawędzie, kiedy vjust=0. To ma dla mnie sens.
Andrie