webentwicklung-frage-antwort-db.com.de

ggplot2 zweizeiliges Label mit Ausdruck

Ich möchte mit zwei Anweisungen eine Achsenbeschriftung mit einer expression()-Anweisung schreiben. plotmath und expression erlauben dies jedoch nicht (z. B. erscheint unten stehender Text ganz rechts). Ich fand diese Diskussion ungefähr 2005 eines ähnlichen Problems, aber die Arbeit, die sie anbieten, lässt sich nicht auf meine Anwendung in ggplot2 übertragen. Eine aktuelle Frage befasste sich mit einer anderen Permutation von Anweisungen für mehrzeilige Ausdrücke, aber auch hier gilt die beschriebene Umgehung nicht.

Beispiel:

p <- ggplot(mtcars,aes(x=wt,y=mpg))+
  geom_point()+
  xlab(expression(paste("A long string of text goes here just for the purpose \n of illustrating my point Weight "[reported])))
try(ggsave(plot=p,filename=<some file>,height=4,width=6))

ergibt ein Bild, in dem der Index "report" nach rechts ausgegeben wird, wenn ich möchte, dass er neben dem vorherigen Wort sitzt.ggplot2 two line label with expression

47
metasequoia

Ich denke das ist ein Fehler. (Oder eine Folge der Tatsache, dass "mehrzeilige Ausdrücke nicht unterstützt werden", wie in der von Ihnen verlinkten Konversation angegeben).

Die Problemumgehung, auf die Gavin Simpson anspielte, ist:

#For convenience redefine p as the unlabeled plot
p <- ggplot(mtcars,aes(x=wt,y=mpg))+geom_point()

#Use atop to fake a line break
p + xlab(expression(atop("A long string of text for the purpose", paste("of illustrating my point" [reported]))))

enter image description here

Bei Subskripten können echte Zeilenumbrüche verwendet werden. In dem folgenden kurzen Beispiel, das dieselbe Form wie Ihr Beispiel hat, ist der Index korrekt neben dem Rest des Textes platziert, die beiden Textzeilen sind jedoch nicht korrekt zentriert:

p + xlab(expression(paste("line1 \n line2 a" [b])))

enter image description here

Ich denke, in beiden Fällen wird der Index falsch platziert, wenn die obere Textzeile länger ist als die untere Textzeile. Vergleichen Sie

p + xlab(expression(paste("abc \n abcd" [reported])))

enter image description here

p + xlab(expression(paste("abc \n ab" [reported])))

enter image description here

Der Index endet immer rechts am rechten Ende der oberen Zeile.

p + xlab(expression(paste("abcdefghijklmnop \n ab" [reported])))

enter image description here

53
Drew Steen

Sie könnten diesen Trick verwenden,

library(gridExtra)
library(grid)

element_custom <- function() {
  structure(list(), class = c("element_custom", "element_text"))
}

element_grob.element_custom <- function(element, label="", ...)  {

  mytheme <- ttheme_minimal(core = list(fg_params = list(parse=TRUE, 
                                                         hjust=0, x=0.1)))
  disect <- strsplit(label, "\\n")[[1]]
  tableGrob(as.matrix(disect), theme=mytheme)
}

# default method is unreliable
heightDetails.gtable <- function(x) sum(x$heights)

ggplot(iris, aes(Sepal.Length, Sepal.Width)) +
  geom_line() + 
  labs(x= "First~line \n italic('and a second') \n integral(f(x)*dx, a, b)")+
  (theme_grey() %+replace% theme(axis.title.x = element_custom()))

 enter image description here

10
baptiste

1) Lösung mit cowplot::draw_label()

Man könnte auch die Annotationsfunktion draw_label() aus dem Paket cowplot verwenden (vorgeschlagen in this discussion). Wir könnten cowplot::draw_label() so viele Textzeilen nennen, die wir haben. Wenn cowplot::draw_label() in Kombination mit cowplot::ggdraw() verwendet wird, können auf der Arbeitsfläche/dem Arbeitsblatt beliebige Koordinaten mit Koordinaten zwischen 0 und 1 (relativ zur gesamten Arbeitsfläche) angegeben werden.

Sie müssen die Anmerkungsposition anpassen und genügend Platz für den benutzerdefinierten Achsentitel schaffen.

Beachten Sie, dass das cowplot-Paket derzeit das standardmäßige ggplot-Design ändert. Verwenden Sie daher nach dem Laden des Pakets theme_set(), wie hier hier .

Beachten Sie auch, dass die Funktion cowplot::draw_label()ggplot2::annotation_custom() unter der Haube verwendet. Ich werde im zweiten Teil weiter unten mehr darüber erzählen.

library(ggplot2)
library(cowplot)
#> 
#> Attaching package: 'cowplot'
#> The following object is masked from 'package:ggplot2':
#> 
#>     ggsave

# If needed, revert to default theme (cowplot modifies the theme); 
# theme_set(theme_grey())

p <- ggplot(mtcars, aes(x = wt, y = mpg)) + geom_point()
# Make enough space for the custom two lines axis title
p <- p + 
  xlab("") + # empty label
  # Tweak the margins (Push the label down by forcing a wider top margin)
  theme(axis.title.x = element_text(size = 10, # also adjust text size if needed
                                    margin = margin(t = 10, r = 0, b = 0, l = 0,
                                                    unit = "mm")))

# The two lines we wish on the plot
line_1 <- "A long string of text for the purpose"
line_2 <- expression(paste("of illustrating my point" [reported]))
# Or avoid paste() (is not actually needed)
# line_2 <- expression("of illustrating my point" [reported])

# Call cowplot::draw_label two times to plot two lines of text
ggdraw(p) + 
  draw_label(line_1, x = 0.55, y = 0.075) + # use relative coordinates for positioning
  draw_label(line_2, x = 0.55, y = 0.025)

Beachten Sie, dass cowplot::draw_label() auch in Kombination mit dem Abschalten der Abschaltung coord_cartesian(clip = "off") verwendet werden kann, wodurch das Plotten von überall auf der Leinwand ermöglicht wird. Diesmal verwenden wir nicht mehr die relativen Koordinaten, sondern die aus der Zeichnung/den Daten (die absoluten Koordinaten):

# Other two expressions
line_1b <- expression(bolditalic('First line'))
line_2b <- expression(integral(f(x)*dx, a, b))

p + coord_cartesian(clip = "off") + # allows plotting anywhere on the canvas
  draw_label(line_1b, x = 3.5, y = 8.2) + # use absolute coordinates for positioning
  draw_label(line_2b, x = 3.5, y = 6)

Erstellt am 14.01.1901 durch das Paket reprex (v0.2.1)


2) Lösung mit ggplot2::annotation_custom()

Wie bereits erwähnt, ist cowplot::draw_label() ein Wrapper von ggplot2::annotation_custom(). Anstelle von cowplot::draw_label() könnten wir also ggplot2::annotation_custom() direkt verwenden, wenn Sie das Clipping deaktivieren - coord_cartesian(clip = "off") -, das beim Zusammenführen von dieser Pull-Anforderung verfügbar wurde.

Dieser Ansatz ist jedoch ausführlicher, mit mehr Koordinatenargumenten, und wir müssen grid::textGrob() verwenden.

# Some other two lines we wish on the plot as OX axis title
line_1c <- expression("Various fonts:" ~ bolditalic("bolditalic") ~ bold("bold") ~ italic("italic"))
line_2c <- expression("this" ~~ sqrt(x, y) ~~ "or this" ~~ sum(x[i], i==1, n) ~~ "math expression")
# the ~~ ads a bit more space than ~ between the expression's components

p + coord_cartesian(clip = "off") +
  annotation_custom(grid::textGrob(line_1c), xmin = 3.5, xmax = 3.5, ymin = 7.3, ymax = 7.3) +
  annotation_custom(grid::textGrob(line_2c), xmin = 3.5, xmax = 3.5, ymin = 5.5, ymax = 5.5)

Erstellt am 14.01.1901 durch das Paket reprex (v0.2.1)

0
Valentin