Wie füge ich einen ggplot2-Untertitel mit unterschiedlicher Größe und Farbe hinzu?


86

Ich benutze ggplot2, um Niederschlags-Barplots zu verbessern.

Hier ist ein reproduzierbares Beispiel dafür, was ich erreichen möchte:

library(ggplot2)
library(gridExtra)
secu <- seq(1, 16, by=2)
melt.d <- data.frame(y=secu, x=LETTERS[1:8])
m <- ggplot(melt.d, aes(x=x, y=y)) +
  geom_bar(fill="darkblue") + 
  labs(x="Weather    stations", y="Accumulated Rainfall [mm]") +
  opts(axis.text.x=theme_text(angle=-45, hjust=0, vjust=1),
       title=expression("Rainfall"), plot.margin = unit(c(1.5, 1, 1, 1), "cm"),
       plot.title = theme_text(size = 25, face = "bold", colour = "black", vjust = 5))
z <- arrangeGrob(m, sub = textGrob("Location", x = 0, hjust = -3.5, vjust = -33, gp = gpar(fontsize = 18, col = "gray40"))) #Or guessing x and y with just option
z

Ich weiß nicht, wie ich es vermeiden soll, auf hjust und vjust auf ggplot2 zu raten? Gibt es eine bessere Möglichkeit, einen Untertitel einzufügen (nicht nur mit \ n, sondern mit einem Untertitel mit unterschiedlicher Textfarbe und -größe)?

Ich muss in der Lage sein, mit ggsave eine PDF-Datei zu haben.

Hier sind zwei verwandte Fragen:

Hinzufügen eines Fußnotenzitats außerhalb des Grundstücksbereichs in R?

Wie kann ich einen Untertitel hinzufügen und die Schriftgröße von ggplot-Plots in R ändern?

Vielen Dank für jede Hilfe.


Das vjust = -33 hat bei mir unter Linux funktioniert. Ich weiß, dass das U-Boot unter die Handlung gehen soll, aber es war der einzige Weg, auf dem ich das bekam, was ich wollte.
Migue

Aus irgendeinem Grund macht dies meine Handlung wirklich klein und schafft einen riesigen Raum unter der Grafik
zazu

2
@hrbrmstrs Antwort scheint heutzutage der
richtige

Antworten:


98

Die neuesten ggplot2-Builds (dh 2.1.0.9000 oder neuer) verfügen über Untertitel und Untertitel unter dem Plot als integrierte Funktionalität. Das heißt, Sie können dies tun:

library(ggplot2) # 2.1.0.9000+ 

secu <- seq(1, 16, by=2)
melt.d <- data.frame(y=secu, x=LETTERS[1:8])

m <-  ggplot(melt.d, aes(x=x, y=y))
m <- m + geom_bar(fill="darkblue", stat="identity")
m <- m + labs(x="Weather    stations", 
              y="Accumulated Rainfall [mm]",
              title="Rainfall",
              subtitle="Location")
m <- m + theme(axis.text.x=element_text(angle=-45, hjust=0, vjust=1)) 
m <- m + theme(plot.title=element_text(size=25, hjust=0.5, face="bold", colour="maroon", vjust=-1))
m <- m + theme(plot.subtitle=element_text(size=18, hjust=0.5, face="italic", color="black"))
m

Fehler in (Funktion (el, elname): "plot.subtitle" ist kein gültiger Name des Themenelements.
Luís de Sousa

1
Bitte lesen Sie die Antworten: "Neueste ggplot2-Builds (dh 2.1.0.9000 oder neuer)"
hrbrmstr

75

Diese Antwort ignorieren ggplot2 Version 2.2.0 verfügt über Titel- und Untertitelfunktionen. Siehe die Antwort von @ hrbrmstr unten .


Sie können verschachtelte atopFunktionen in einem verwendenexpression , um verschiedene Größen zu erhalten.

EDIT Aktualisiert Code für ggplot2 0.9.3

m <-  ggplot(melt.d, aes(x=x, y=y)) + 
     geom_bar(fill="darkblue", stat = "identity") + 
     labs(x="Weather    stations", y="Accumulated Rainfall [mm]") + 
     ggtitle(expression(atop("Rainfall", atop(italic("Location"), "")))) +
     theme(axis.text.x = element_text(angle=-45, hjust=0, vjust=1), 
     #plot.margin = unit(c(1.5, 1, 1, 1), "cm"), 
     plot.title = element_text(size = 25, face = "bold", colour = "black", vjust = -1))

Geben Sie hier die Bildbeschreibung ein


10
Hallo, das ist eine erstaunliche Lösung. Ich würde es gerne benutzen, aber stattdessen atop(italic("Location")möchte ich ein Objekt haben : atop(italic(my_string_vector). Ich habe das versucht, aber dann wurde der Untertitel zu (my_string_vector) ausgewertet . Wie kann man diesen Ausdruck zwingen, den Zeichenfolgenwert zu verwenden und den bereitgestellten Text nicht wörtlich zu behandeln?
Konrad

1
Falls Sie Probleme mit der Verwendung von Variablen haben, die Sie bquoteanstelle von verwenden sollten expression, siehe hier
toto_tico

3
@Konrad Zur Verwendung Objekte, ersetzen expressionmit bquoteund wickeln Sie die Objekte mit .(), wie diese, für einen Haupttitel in einem Objekt gespeichert als „main.title“ und für einen Untertitel in einem Objekt gespeichert namens „sub.title“: ggtitle(bquote(atop(.(main.title), atop(italic(.(sub.title)), "")))) Kredit geht zu Didzis Elferts 'Antwort hier: stackoverflow.com/questions/19957536/…
coip

10

Es scheint optsab ggplot 2 0.9.1 veraltet und nicht mehr funktionsfähig zu sein. Dies funktionierte bei mir mit den neuesten Versionen ab heute : + ggtitle(expression(atop("Top line", atop(italic("2nd line"), "")))).


Dies funktioniert auch ohne das Finale , ""- wofür ist dieser Teil?
naught101

Schlägt mich. Ich habe vielleicht ein Beispiel kopiert, das ich woanders gesehen habe.
Aren Cambre

Wahrscheinlich aus der obigen Antwort von @ SandyMuspratt: P - Ich verstehe es jetzt, atop()ist so etwas wie ein Bruchteil ohne Balken. Wenn Sie also die zweite atop()in die erste setzen, erhalten Sie einen Unterbruch, wobei der Text proportional kleiner ist. Das ""ist der Boden der Unterfraktion. Es scheint jedoch unnötig zu sein - hat möglicherweise atop()eine leere Standardzeichenfolge für den zweiten Parameter oder so.
Naught101

Es scheint, dass die Antwort von @ SandyMuspratt geändert wurde, nachdem ich meine Antwort veröffentlicht habe, um einen Code zu reflektieren, der meinem ähnlich ist. :-)
Aren Cambre

9

Es ist nicht allzu schwer, dem gtable Grobs hinzuzufügen und auf diese Weise einen ausgefallenen Titel zu erstellen.

library(ggplot2)
library(grid)
library(gridExtra)
library(magrittr)
library(gtable)

p <- ggplot() + 
  theme(plot.margin = unit(c(0.5, 1, 1, 1), "cm"))

lg <- list(textGrob("Rainfall", x=0, hjust=0, 
                    gp = gpar(fontsize=24, fontfamily="Skia", face=2, col="turquoise4")),
               textGrob("location", x=0, hjust=0, 
                        gp = gpar(fontsize=14, fontfamily="Zapfino", fontface=3, col="violetred1")),
           pointsGrob(pch=21, gp=gpar(col=NA, cex=0.5,fill="steelblue")))

margin <- unit(0.2, "line")
tg <- arrangeGrob(grobs=lg, layout_matrix=matrix(c(1,2,3,3), ncol=2),
                  widths = unit.c(grobWidth(lg[[1]]), unit(1,"null")),
                  heights = do.call(unit.c, lapply(lg[c(1,2)], grobHeight)) + margin)

grid.newpage()
ggplotGrob(p) %>%
  gtable_add_rows(sum(tg$heights), 0) %>%
  gtable_add_grob(grobs=tg, t = 1, l = 4)  %>%
  grid.draw()

Geben Sie hier die Bildbeschreibung ein


8

Diese Version verwendet eine gtableFunktion. Es erlaubt zwei Textzeilen im Titel. Der Text, die Größe, die Farbe und die Schriftfläche jeder Zeile können unabhängig voneinander festgelegt werden. Die Funktion ändert jedoch ein Diagramm nur mit einem einzelnen Diagrammfenster.

Kleinere Änderungen: Aktualisierung auf ggplot2 v2.0.0

# The original plot
library(ggplot2)

secu <- seq(1, 16, by = 2)
melt.d <- data.frame(y = secu, x = LETTERS[1:8])

m <- ggplot(melt.d, aes(x = x, y = y)) + 
     geom_bar(fill="darkblue", stat = "identity") + 
     labs(x = "Weather    stations", y = "Accumulated Rainfall [mm]") + 
     theme(axis.text.x = element_text(angle = -45, hjust = 0, vjust = 1))


# The function to set text, size, colour, and face
plot.title = function(plot = NULL, text.1 = NULL, text.2 = NULL, 
   size.1 = 12,  size.2 = 12,
   col.1 = "black", col.2 = "black", 
   face.1 = "plain",  face.2 = "plain") {

library(gtable)
library(grid)

gt = ggplotGrob(plot)

text.grob1 = textGrob(text.1, y = unit(.45, "npc"), 
   gp = gpar(fontsize = size.1, col = col.1, fontface = face.1))
text.grob2 = textGrob(text.2,  y = unit(.65, "npc"), 
   gp = gpar(fontsize = size.2, col = col.2, fontface = face.2))

text = matrix(list(text.grob1, text.grob2), nrow = 2)
text = gtable_matrix(name = "title", grobs = text, 
   widths = unit(1, "null"), 
   heights = unit.c(unit(1.1, "grobheight", text.grob1) + unit(0.5, "lines"), unit(1.1,  "grobheight", text.grob2) + unit(0.5, "lines")))

gt = gtable_add_grob(gt, text, t = 2, l = 4)
gt$heights[2] = sum(text$heights)

class(gt) =  c("Title", class(gt))

gt
}

# A print method for the plot
print.Title <- function(x) {
   grid.newpage()   
   grid.draw(x)
}


# Try it out - modify the original plot
p = plot.title(m, "Rainfall", "Location", 
   size.1 = 20, size.2 = 15, 
   col.1 = "red", col.2 = "blue", 
   face.2 = "italic")

p

Geben Sie hier die Bildbeschreibung ein


3

Sie können das Diagramm in grid.arrange umbrechen und einen benutzerdefinierten gitterbasierten Titel übergeben.

Geben Sie hier die Bildbeschreibung ein

library(ggplot2)
library(gridExtra)

p <- ggplot() + 
  theme(plot.margin = unit(c(0.5, 1, 1, 1), "cm"))

tg <- grobTree(textGrob("Rainfall", y=1, vjust=1, gp = gpar(fontsize=25, face=2, col="black")),
               textGrob("location", y=0, vjust=0, gp = gpar(fontsize=12, face=3, col="grey50")),
               cl="titlegrob")
heightDetails.titlegrob <- function(x) do.call(sum,lapply(x$children, grobHeight))

grid.arrange(p, top = tg)

Aktuelle Versionen von ggplot verwenden theme und und element_text anstelle von opts bzw. theme_text. Außerdem scheint der ggplotGrob-Ansatz in der aktuellen Version von gridExtra (gridExtra_0.8.1) und ggplot2 (ggplot2_0.9.3.1)
russellpierce am

2

Möglicherweise haben Sie bemerkt, dass Sandys Code keinen fett gedruckten Titel für "Rainfall" erzeugt. Die Anweisung, dies fett zu machen, sollte in der Funktion atop () und nicht in der Funktion theme () erfolgen.

ggplot(melt.d, aes(x=x, y=y)) + 
 geom_bar(fill="darkblue", stat = "identity") + 
 labs(x="Weather    stations", y="Accumulated Rainfall [mm]") + 
 ggtitle(expression(atop(bold("Rainfall"), atop(italic("Location"), "")))) +
 theme(axis.text.x = element_text(angle=-45, hjust=0, vjust=1),
 plot.title = element_text(size = 25, colour = "black", vjust = -1))

Geben Sie hier die Bildbeschreibung ein

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.