Bagaimana cara menambahkan subtitle ggplot2 dengan ukuran dan warna yang berbeda?

89

Saya menggunakan ggplot2 untuk meningkatkan barplot presipitasi.

Berikut adalah contoh yang dapat direproduksi dari apa yang ingin saya capai:

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

Saya tidak tahu bagaimana menghindari penggunaan angka menebak di hjust dan vjust di ggplot2? Adakah cara yang lebih baik untuk meletakkan subtitle (tidak hanya menggunakan \ n, tetapi subtitle dengan warna dan ukuran teks yang berbeda)?

Saya harus dapat menggunakan ggsave untuk memiliki file pdf.

Berikut dua pertanyaan terkait:

Tambahkan kutipan catatan kaki di luar area plot di R?

Bagaimana cara menambahkan subtitle dan mengubah ukuran font plot ggplot di R?

Terima kasih atas bantuannya.

Migue
sumber
Vjust = -33 bekerja untuk saya di Linux. Saya tahu bahwa sub dimaksudkan untuk pergi ke bawah plot, tetapi itu satu-satunya cara saya mendapatkan apa yang saya inginkan.
Bermigrasi
untuk beberapa alasan ini membuat plot saya sangat kecil dan menciptakan ruang yang sangat besar di bawah grafik
zazu
2
Jawaban @hrbrmstr s sepertinya cara untuk pergi saat ini
andschar

Jawaban:

103

Versi ggplot2 terbaru (yaitu, 2.1.0.9000 atau yang lebih baru) memiliki subtitle dan teks di bawah plot sebagai fungsionalitas bawaan. Itu artinya Anda bisa melakukan ini:

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
hrbrmstr
sumber
Kesalahan dalam (fungsi (el, elname): "plot.subtitle" bukan nama elemen tema yang valid.
Luís de Sousa
1
Harap baca jawaban: "versi ggplot2 terbaru (yaitu, 2.1.0.9000 atau yang lebih baru)"
hrbrmstr
75

Abaikan jawaban ini ggplot2 versi 2.2.0 memiliki fungsi judul dan subtitle. Lihat jawaban @ hrbrmstr di bawah ini .


Anda bisa menggunakan atopfungsi bertingkat di dalam expressionuntuk mendapatkan ukuran yang berbeda.

EDIT Kode yang diperbarui untuk 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))

masukkan deskripsi gambar di sini

Sandy Muspratt
sumber
10
Hai, ini adalah solusi yang luar biasa. Saya ingin menggunakannya tapi bukannya atop(italic("Location")saya ingin memiliki objek: atop(italic(my_string_vector). Saya mencobanya tetapi kemudian subtitle dievaluasi ke (my_string_vector) . Bagaimana cara memaksa ekspresi ini untuk menggunakan nilai string dan tidak memperlakukan teks yang disediakan secara harfiah?
Konrad
1
jika anda mengalami masalah menggunakan variabel Anda harus menggunakan bquotebukan expression, lihat di sini
toto_tico
3
@Konrad Untuk menggunakan objek, ganti expressiondengan bquotedan bungkus objek dengan .(), seperti ini, untuk judul utama yang disimpan dalam objek yang disebut "main.title" dan untuk subtitle yang disimpan dalam objek yang disebut "sub.title": ggtitle(bquote(atop(.(main.title), atop(italic(.(sub.title)), "")))) Penghargaan diberikan kepada Didzis Jawaban Elferts di sini: stackoverflow.com/questions/19957536/…
coip
10

Tampaknya optssudah usang pada ggplot 2 0.9.1 dan tidak lagi berfungsi. Ini bekerja untuk saya dengan versi terbaru hari ini: + ggtitle(expression(atop("Top line", atop(italic("2nd line"), "")))).

Aren Cambre
sumber
Ini juga bekerja tanpa final , ""- untuk apa bagian itu?
ada101
Pukul aku. Saya mungkin telah menyalin contoh yang saya lihat di tempat lain.
Aren Cambre
Mungkin dari jawaban @ SandyMuspratt di atas: P - Saya mengerti sekarang, atop()itu seperti pecahan tanpa batang. Jadi meletakkan yang kedua atop()di dalam yang pertama memberi Anda sub-pecahan, dengan teks lebih kecil secara proporsional. Ini ""adalah bagian bawah pecahan. Tampaknya tidak perlu - mungkin atop()memiliki string kosong default untuk parameter kedua, atau sesuatu.
n nothing101
Tampaknya jawaban @SandyMuspratt telah diubah setelah saya memposting jawaban saya untuk mencerminkan kode yang mirip dengan milik saya. :-)
Aren Cambre
9

tidak terlalu sulit untuk menambahkan grobs ke gtable dan membuat judul yang keren seperti itu,

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

masukkan deskripsi gambar di sini

baptiste
sumber
8

Versi ini menggunakan gtablefungsi. Ini memungkinkan dua baris teks dalam judul. Teks, ukuran, warna, dan tampilan font setiap baris dapat disetel secara terpisah satu sama lain. Namun, fungsi tersebut akan mengubah plot hanya dengan satu panel plot.

Pengeditan kecil: Memperbarui ke 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

masukkan deskripsi gambar di sini

Sandy Muspratt
sumber
3

Anda bisa menggunakan bungkus plot dalam grid.arrange dan berikan judul berbasis grid kustom,

masukkan deskripsi gambar di sini

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)
baptiste
sumber
Versi ggplot saat ini menggunakan tema dan dan element_text, bukan opts dan theme_text. Selain itu, pendekatan ggplotGrob tampaknya gagal dalam versi gridExtra (gridExtra_0.8.1) dan ggplot2 (ggplot2_0.9.3.1) saat ini
russellpierce
2

Anda mungkin telah memperhatikan bahwa kode Sandy tidak menghasilkan judul tebal untuk "Rainfall" - instruksi untuk membuat tebal ini harus muncul dalam fungsi atop () daripada fungsi theme ().

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

masukkan deskripsi gambar di sini

Nathan
sumber