grid_plot + tikzDevice + 带有乳胶标记的共享图例
grid_plot + tikzDevice + shared legend with latex mark up
我一直在尝试关注 this vignette 如何为多个 ggplot2 创建共享图例。给定的示例按原样完美运行,但就我而言,我正在使用 tikzDevice 导出 tikzpicture
环境。主要问题似乎是 grid_plot
.
未正确捕获图例键的宽度
我想出了一个重现问题的最小 R 代码:
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()
生成的PDF文件(编译后tmp.tex)如下所示:
我们可以观察到,第一个图例键(四)仅部分显示,图例键(八)完全不可见。我尝试更改 tikz
命令宽度无济于事。
此外,我怀疑问题背后的原因是 grid_plot 命令错误地测量了包含乳胶标记的图例键的长度。要表明这是问题的原因,请考虑将 mpg2$cyl 的级别更改为以下内容:
levels(mpg2$cyl) <- c("four",
"five",
"six",
"seven",
"eight")
这应该会产生以下具有完美图例的情节:
请注意,上面的例子只是为了重现问题,并不是我想要做的。相反,我有四个图,我试图为它们使用一个共享的通用图例。
任何人都可以告诉我如何解决包含乳胶标记的图例问题?
顺便说一句,这是我的 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
谢谢大家
也许引入一个对字符串宽度影响不大的临时标记更容易,post-在 R 和 latex 步骤之间处理 tex 文件,
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")
ggplot2 似乎是根据原始字符串计算字符串宽度,而不是应该由 TeX 返回的框大小。我猜这是指南代码中过早完成的计算(即不是在绘图时)。
作为解决方法,您可以通过显式调用 getLatexStrWidth
在 gtable 中手动编辑相关宽度。注意我还在序言中添加了一个包,否则默认字体不会显示粗体小写字母。
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()
我一直在尝试关注 this vignette 如何为多个 ggplot2 创建共享图例。给定的示例按原样完美运行,但就我而言,我正在使用 tikzDevice 导出 tikzpicture
环境。主要问题似乎是 grid_plot
.
我想出了一个重现问题的最小 R 代码:
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()
生成的PDF文件(编译后tmp.tex)如下所示:
我们可以观察到,第一个图例键(四)仅部分显示,图例键(八)完全不可见。我尝试更改 tikz
命令宽度无济于事。
此外,我怀疑问题背后的原因是 grid_plot 命令错误地测量了包含乳胶标记的图例键的长度。要表明这是问题的原因,请考虑将 mpg2$cyl 的级别更改为以下内容:
levels(mpg2$cyl) <- c("four",
"five",
"six",
"seven",
"eight")
这应该会产生以下具有完美图例的情节:
请注意,上面的例子只是为了重现问题,并不是我想要做的。相反,我有四个图,我试图为它们使用一个共享的通用图例。
任何人都可以告诉我如何解决包含乳胶标记的图例问题?
顺便说一句,这是我的 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
谢谢大家
也许引入一个对字符串宽度影响不大的临时标记更容易,post-在 R 和 latex 步骤之间处理 tex 文件,
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")
ggplot2 似乎是根据原始字符串计算字符串宽度,而不是应该由 TeX 返回的框大小。我猜这是指南代码中过早完成的计算(即不是在绘图时)。
作为解决方法,您可以通过显式调用 getLatexStrWidth
在 gtable 中手动编辑相关宽度。注意我还在序言中添加了一个包,否则默认字体不会显示粗体小写字母。
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()