2017-04-07 2 views
4

Ich habe versucht, this vignette zu folgen, wie man eine geteilte Legende für mehrfaches ggplot2 bildet. Die angegebenen Beispiele funktionieren einwandfrei, aber in meinem Fall verwende ich tikzDevice, um eine tikzpicture-Umgebung zu exportieren. Das Hauptproblem scheint zu sein, dass die Breiten der Legendenschlüssel nicht korrekt von grid_plot erfasst werden.grid_plot + tikzDevice + geteilte Legende mit Latexmarkierung

Ich kam mit einem minimalen R-Code auf, der das Problem reproduziert:

require(ggplot2) 
require(grid) 
require(gridExtra) 
require(cowplot) 
require(tikzDevice) 

tikz(file = "./tmp.tex", width = 5.6, height = 2.2, standAlone = T) 
mpg2 <- mpg 

mpg2$cyl = as.factor(mpg2$cyl) 
levels(mpg2$cyl) <- c("\\textbf{\\textsc{four}}", 
         "\\textbf{\\textsc{five}}", 
         "\\textbf{\\textsc{six}}", 
         "\\textbf{\\textsc{seven}}", 
         "\\textbf{\\textsc{eight}}") 

plot.mpg <- ggplot(mpg2, aes(x=cty, colour=cyl, y = hwy)) + 
    geom_point() + 
    theme(legend.position='none') 

legend <- get_legend(plot.mpg + theme(legend.position = "top")) 

print(plot_grid(legend, 
       plot.mpg, nrow=2, ncol=1,align='h', 
       rel_heights = c(.1, 1))) 

dev.off() 

Die generierte PDF-Datei (nach dem Kompilieren tmp.tex) sieht wie folgt aus:

enter image description here

Wie wir kann beobachten, der erste Legendenschlüssel (vier) wird nur teilweise angezeigt und der Legendenschlüssel (acht) ist komplett unsichtbar. Ich habe versucht, tikz Befehlsbreite vergeblich zu ändern.

Außerdem vermute ich, dass der Grund für das Problem ist, dass Grid_plot Befehl die Länge der Legendenschlüssel falsch misst, wenn sie Latex Mark up enthalten. Um zu zeigen, dass dies die Ursache des Problems ist, sollten Sie die Ebenen des mpg2 $ Zyl Wechsel auf die folgenden:

levels(mpg2$cyl) <- c("four", 
         "five", 
         "six", 
         "seven", 
         "eight") 

Dies sollte mit einer perfekten Legende in der folgenden Handlung führen:

enter image description here

Bitte beachten Sie, dass das obige Beispiel nur dazu gedacht ist, das Problem zu reproduzieren und nicht das, was ich versuche zu tun. Stattdessen habe ich vier Diagramme, die ich versuche, eine gemeinsame gemeinsame Legende für sie zu verwenden.

Wer kann mir bitte sagen, wie ich das Legendenproblem beheben kann, wenn es Latexmarkierung enthält?

By the way, hier ist mein sessionInfo():

R version 3.3.2 (2016-10-31) 
Platform: x86_64-apple-darwin13.4.0 (64-bit) 
Running under: OS X Yosemite 10.10.5 

locale: 
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8 

attached base packages: 
[1] grid  stats  graphics grDevices utils  datasets methods 
[8] base  

other attached packages: 
[1] tikzDevice_0.10-1 dplyr_0.5.0  gdata_2.17.0  cowplot_0.7.0  
[5] gridExtra_2.2.1 ggplot2_2.2.0  

loaded via a namespace (and not attached): 
[1] gtools_3.5.0  colorspace_1.2-6 DBI_0.5   RColorBrewer_1.1-2 
[5] plyr_1.8.4   munsell_0.4.3  gtable_0.2.0  labeling_0.3  
[9] Rcpp_0.12.6  scales_0.4.1  filehash_2.3  digest_0.6.10  
[13] tools_3.3.2  magrittr_1.5  lazyeval_0.2.0  tibble_1.1   
[17] assertthat_0.1  R6_2.1.3   

Vielen Dank.

Antwort

4

ggplot2 erscheint die Zeichenfolge Breiten auf der Basis des rohen String zu berechnen, im Gegensatz Größen boxen, die von TeX zurückgegeben werden sollen. Ich nehme an, dass es eine Berechnung ist, die zu früh (dh nicht zum Zeitpunkt des Zeichnens) im Guides Code gemacht wurde. Als Workaround konnten Sie die relevanten Breiten manuell in der gtable bearbeiten, indem Sie explizit getLatexStrWidth aufrufen. Hinweis: Ich fügte auch ein Paket in der Präambel hinzu, andernfalls zeigt die Standardschrift keine fettgedruckten Kapitälchen.

require(ggplot2) 
require(grid) 
require(gridExtra) 
require(tikzDevice) 

setTikzDefaults(overwrite = TRUE) 
preamble <- options("tikzLatexPackages") 
options("tikzLatexPackages" = c(preamble$tikzLatexPackages, "\\usepackage{bold-extra}")) 

tikz(file = "./tmp.tex", width = 5.6, height = 2.2, standAlone = TRUE) 
mpg2 <- mpg 

mpg2$cyl = as.factor(mpg2$cyl) 

levels(mpg2$cyl) <- c("\\textbf{\\textsc{four}}", 
         "\\textbf{\\textsc{five}}", 
         "\\textbf{\\textsc{six}}", 
         "\\textbf{\\textsc{seven}}", 
         "\\textbf{\\textsc{eight}}") 

p <- ggplot(mpg2, aes(x=cty, colour=cyl, y = hwy)) + 
    geom_point() + 
    theme(legend.position='none') 



leg <- cowplot::get_legend(p + theme(legend.position = "top")) 

ids <- grep("label",leg$grobs[[1]]$layout$name) 
pos <- leg$grobs[[1]]$layout$l[ids] 
wl <- sapply(leg$grobs[[1]][["grobs"]][ids], function(g) getLatexStrWidth(g[["label"]])) 

leg$grobs[[1]][["widths"]][pos] <- unit(wl, "pt") 

grid.arrange(p, top=leg) 

dev.off() 

enter image description here

1

Vielleicht ist es einfacher, eine temporäre Markup einzuführen, die nicht viel die Zeichenfolge Breite nicht beeinflusst, und nachbearbeiten die tex-Datei zwischen R und Latex Schritten

levels(mpg2$cyl) <- c("$four$", 
         "$five$", 
         "$six$", 
         "$seven$", 
         "$eight$") 

[...]

tmp <- readLines("tmp.tex") 
gs <- gsub("\\$(four|five|six|seven|eight)\\$", "\\\\textsc{\\1}", tmp, perl=TRUE) 
cat(paste(gs, collapse="\n"), file="tmp2.tex") 

enter image description here

+0

alternativ Verwendung Strings wie '\ vier, \ fünf, etc.' und definieren sie in der Präambel tex (obwohl Spielraümen schmerzhaft erweisen). – baptiste

+0

Diese Antwort ist ein Beispiel für "über den Tellerrand hinaus denken". Vielen Dank! – user8420488483439