在将 gridExtra 更新到 2.0.0 后使用 ggsave 和 arrangeGrob
using ggsave and arrangeGrob after updating gridExtra to 2.0.0
由于到目前为止我在Whosebug上阅读了很多类似的问题,所以在不将ggplot2更新到开发版本的情况下找不到好的解决方案。
我的问题是,我有几个脚本使用 arrangeGrob
从单个图形中创建组合图形。我将它们保存到一个变量中,然后 print
这个变量 and/or 用 ggsave
保存它。由于我的很多同事定期更新那里的软件包(我认为这是一件好事),我总是收到邮件我的脚本在更新到 gridExtra 2.0.0
.
后不再工作
我不确定如何处理这个问题,因为解决问题的新 ggplot2
版本仍在开发中。我发现一个 article on stack overflow 删除测试如果要保存的对象是一个 ggplot
因为新的 arrangeGrob
函数 returns 一个 gtable
对象,但是这对我来说失败了:
library(ggplot2)
library(grid)
library(gridExtra)
a <- data.frame(x=c(1,2,3),
y=c(2,3,4))
p <- ggplot(a, aes(x, y)) + geom_point()
b <- arrangeGrob(p, p)
grid.draw(b)
ggsave('test.pdf', b)
ggsave <- ggplot2::ggsave
body(ggsave) <- body(ggplot2::ggsave)[-2]
ggsave('test.pdf', b)
控制台上的一些输出和错误:
d> grid.draw(b)
d> ggsave('test.pdf', b)
Error in ggsave("test.pdf", b) : plot should be a ggplot2 plot
d> ggsave <- ggplot2::ggsave
d> body(ggsave) <- body(ggplot2::ggsave)[-2]
d> ggsave('test.pdf', b)
Saving 10.5 x 10.7 in image
TableGrob (2 x 1) "arrange": 2 grobs
z cells name grob
1 1 (1-1,1-1) arrange gtable[layout]
2 2 (2-2,1-1) arrange gtable[layout]
d>
test.pdf
已创建,但已损坏且无法打开。 gtable
对象也被打印出来。所以我想这里有问题。
但是,如您所见,我在示例代码中找到了 grid.draw
函数来绘制至少我的组合图,但修改后我仍然无法 ggsave
它。
我不想使用 中建议的 "old" (pdf(file = "test.pdf"); grid.draw(b); dev.off()
) 设备保存功能,因为它们用起来很不舒服。
在 中有人确切地询问了如何保存对象,但在答案中他们只是解释使用 grid.darw
并且他接受了 solving the problem
的答案并且没有人回答我的问题到目前为止的评论。
所以我现在很迷茫,如何为那些已经和没有更新到新 gridExtra
包的人提供工作脚本。在 ggsave
函数中删除测试的方法是我猜最好的解决方案,因为我可以检查 gridExtra
和 ggplot2
版本并覆盖 ggsave
函数以防万一版本不匹配,但我无法将其设置为 运行。
期待得到一些帮助。
编辑:
也许 sessionInfo
有帮助
d> sessionInfo()
R version 3.2.0 (2015-04-16)
Platform: x86_64-apple-darwin13.4.0 (64-bit)
Running under: OS X 10.9.5 (Mavericks)
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 base
other attached packages:
[1] gridExtra_2.0.0 ggplot2_1.0.1
loaded via a namespace (and not attached):
[1] Rcpp_0.12.1 digest_0.6.8 MASS_7.3-44 plyr_1.8.3 gtable_0.1.2
[6] magrittr_1.5 scales_0.3.0 stringi_1.0-1 reshape2_1.4.1 devtools_1.9.1
[11] proto_0.3-10 tools_3.2.0 stringr_1.0.0 munsell_0.4.2 colorspace_1.2-6
[16] memoise_0.2.1
Pascal 最终让我想到检查 ggplot 1.0.1
和 ggplot 1.0.1.9003
之间的区别,因为我不想或强制使用 ggplot
的开发版本。
所以我的想法是在每个覆盖默认 ggsave
函数的脚本中执行一个函数。
我现在稍微测试了一下,如果有什么BUG之类的,请告诉我。但是我现在这样做的方式到目前为止是有效的。
repairGgsave <- function() {
ggplot_version <-
compareVersion(as.character(packageVersion('ggplot2')),
'1.0.1.9003')
gridextra_version <-
compareVersion(as.character(packageVersion('gridExtra')),
'0.9.1')
if(gridextra_version > 0) {
if(ggplot_version <= 0) {
ggsave <- function(filename, plot = last_plot(),
device = NULL, path = NULL, scale = 1,
width = NA, height = NA, units = c("in", "cm", "mm"),
dpi = 300, limitsize = TRUE, ...) {
dev <- plot_dev(device, filename, dpi = dpi)
dim <- plot_dim(c(width, height), scale = scale, units = units,
limitsize = limitsize)
if (!is.null(path)) {
filename <- file.path(path, filename)
}
dev(file = filename, width = dim[1], height = dim[2], ...)
on.exit(utils::capture.output(grDevices::dev.off()))
grid.draw(plot)
invisible()
}
assign("ggsave", ggsave, .GlobalEnv)
plot_dim <<- function(dim = c(NA, NA), scale = 1, units = c("in", "cm", "mm"),
limitsize = TRUE) {
units <- match.arg(units)
to_inches <- function(x) x / c(`in` = 1, cm = 2.54, mm = 2.54 * 10)[units]
from_inches <- function(x) x * c(`in` = 1, cm = 2.54, mm = 2.54 * 10)[units]
dim <- to_inches(dim) * scale
if (any(is.na(dim))) {
if (length(grDevices::dev.list()) == 0) {
default_dim <- c(7, 7)
} else {
default_dim <- dev.size() * scale
}
dim[is.na(dim)] <- default_dim[is.na(dim)]
dim_f <- prettyNum(from_inches(dim), digits = 3)
message("Saving ", dim_f[1], " x ", dim_f[2], " ", units, " image")
}
if (limitsize && any(dim >= 50)) {
stop("Dimensions exceed 50 inches (height and width are specified in '",
units, "' not pixels). If you're sure you a plot that big, use ",
"`limitsize = FALSE`.", call. = FALSE)
}
dim
}
plot_dev <<- function(device, filename, dpi = 300) {
if (is.function(device))
return(device)
eps <- function(...) {
grDevices::postscript(..., onefile = FALSE, horizontal = FALSE,
paper = "special")
}
devices <- list(
eps = eps,
ps = eps,
tex = function(...) grDevices::pictex(...),
pdf = function(..., version = "1.4") grDevices::pdf(..., version = version),
svg = function(...) grDevices::svg(...),
emf = function(...) grDevices::win.metafile(...),
wmf = function(...) grDevices::win.metafile(...),
png = function(...) grDevices::png(..., res = dpi, units = "in"),
jpg = function(...) grDevices::jpeg(..., res = dpi, units = "in"),
jpeg = function(...) grDevices::jpeg(..., res = dpi, units = "in"),
bmp = function(...) grDevices::bmp(..., res = dpi, units = "in"),
tiff = function(...) grDevices::tiff(..., res = dpi, units = "in")
)
if (is.null(device)) {
device <- tolower(tools::file_ext(filename))
}
if (!is.character(device) || length(device) != 1) {
stop("`device` must be NULL, a string or a function.", call. = FALSE)
}
dev <<- devices[[device]]
if (is.null(dev)) {
stop("Unknown graphics device '", device, "'", call. = FALSE)
}
dev
}
}
}
}
它基本上覆盖了 ggsave
并从开发版本创建了两个新函数。
执行函数后一切正常。
作为这个不幸的过渡期的临时解决方法,您可以重新实施 class 曾经在 gridExtra 中的 hack,
class(b) <- c("arrange","ggplot", class(b))
print.arrange <- function(x) grid.draw(x)
ggsave('test.pdf', b)
为我修复的是明确定义文件:
ggsave(file='test.pdf', b)
由于到目前为止我在Whosebug上阅读了很多类似的问题,所以在不将ggplot2更新到开发版本的情况下找不到好的解决方案。
我的问题是,我有几个脚本使用 arrangeGrob
从单个图形中创建组合图形。我将它们保存到一个变量中,然后 print
这个变量 and/or 用 ggsave
保存它。由于我的很多同事定期更新那里的软件包(我认为这是一件好事),我总是收到邮件我的脚本在更新到 gridExtra 2.0.0
.
我不确定如何处理这个问题,因为解决问题的新 ggplot2
版本仍在开发中。我发现一个 article on stack overflow 删除测试如果要保存的对象是一个 ggplot
因为新的 arrangeGrob
函数 returns 一个 gtable
对象,但是这对我来说失败了:
library(ggplot2)
library(grid)
library(gridExtra)
a <- data.frame(x=c(1,2,3),
y=c(2,3,4))
p <- ggplot(a, aes(x, y)) + geom_point()
b <- arrangeGrob(p, p)
grid.draw(b)
ggsave('test.pdf', b)
ggsave <- ggplot2::ggsave
body(ggsave) <- body(ggplot2::ggsave)[-2]
ggsave('test.pdf', b)
控制台上的一些输出和错误:
d> grid.draw(b)
d> ggsave('test.pdf', b)
Error in ggsave("test.pdf", b) : plot should be a ggplot2 plot
d> ggsave <- ggplot2::ggsave
d> body(ggsave) <- body(ggplot2::ggsave)[-2]
d> ggsave('test.pdf', b)
Saving 10.5 x 10.7 in image
TableGrob (2 x 1) "arrange": 2 grobs
z cells name grob
1 1 (1-1,1-1) arrange gtable[layout]
2 2 (2-2,1-1) arrange gtable[layout]
d>
test.pdf
已创建,但已损坏且无法打开。 gtable
对象也被打印出来。所以我想这里有问题。
但是,如您所见,我在示例代码中找到了 grid.draw
函数来绘制至少我的组合图,但修改后我仍然无法 ggsave
它。
我不想使用 pdf(file = "test.pdf"); grid.draw(b); dev.off()
) 设备保存功能,因为它们用起来很不舒服。
在 grid.darw
并且他接受了 solving the problem
的答案并且没有人回答我的问题到目前为止的评论。
所以我现在很迷茫,如何为那些已经和没有更新到新 gridExtra
包的人提供工作脚本。在 ggsave
函数中删除测试的方法是我猜最好的解决方案,因为我可以检查 gridExtra
和 ggplot2
版本并覆盖 ggsave
函数以防万一版本不匹配,但我无法将其设置为 运行。
期待得到一些帮助。
编辑:
也许 sessionInfo
有帮助
d> sessionInfo()
R version 3.2.0 (2015-04-16)
Platform: x86_64-apple-darwin13.4.0 (64-bit)
Running under: OS X 10.9.5 (Mavericks)
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 base
other attached packages:
[1] gridExtra_2.0.0 ggplot2_1.0.1
loaded via a namespace (and not attached):
[1] Rcpp_0.12.1 digest_0.6.8 MASS_7.3-44 plyr_1.8.3 gtable_0.1.2
[6] magrittr_1.5 scales_0.3.0 stringi_1.0-1 reshape2_1.4.1 devtools_1.9.1
[11] proto_0.3-10 tools_3.2.0 stringr_1.0.0 munsell_0.4.2 colorspace_1.2-6
[16] memoise_0.2.1
Pascal 最终让我想到检查 ggplot 1.0.1
和 ggplot 1.0.1.9003
之间的区别,因为我不想或强制使用 ggplot
的开发版本。
所以我的想法是在每个覆盖默认 ggsave
函数的脚本中执行一个函数。
我现在稍微测试了一下,如果有什么BUG之类的,请告诉我。但是我现在这样做的方式到目前为止是有效的。
repairGgsave <- function() {
ggplot_version <-
compareVersion(as.character(packageVersion('ggplot2')),
'1.0.1.9003')
gridextra_version <-
compareVersion(as.character(packageVersion('gridExtra')),
'0.9.1')
if(gridextra_version > 0) {
if(ggplot_version <= 0) {
ggsave <- function(filename, plot = last_plot(),
device = NULL, path = NULL, scale = 1,
width = NA, height = NA, units = c("in", "cm", "mm"),
dpi = 300, limitsize = TRUE, ...) {
dev <- plot_dev(device, filename, dpi = dpi)
dim <- plot_dim(c(width, height), scale = scale, units = units,
limitsize = limitsize)
if (!is.null(path)) {
filename <- file.path(path, filename)
}
dev(file = filename, width = dim[1], height = dim[2], ...)
on.exit(utils::capture.output(grDevices::dev.off()))
grid.draw(plot)
invisible()
}
assign("ggsave", ggsave, .GlobalEnv)
plot_dim <<- function(dim = c(NA, NA), scale = 1, units = c("in", "cm", "mm"),
limitsize = TRUE) {
units <- match.arg(units)
to_inches <- function(x) x / c(`in` = 1, cm = 2.54, mm = 2.54 * 10)[units]
from_inches <- function(x) x * c(`in` = 1, cm = 2.54, mm = 2.54 * 10)[units]
dim <- to_inches(dim) * scale
if (any(is.na(dim))) {
if (length(grDevices::dev.list()) == 0) {
default_dim <- c(7, 7)
} else {
default_dim <- dev.size() * scale
}
dim[is.na(dim)] <- default_dim[is.na(dim)]
dim_f <- prettyNum(from_inches(dim), digits = 3)
message("Saving ", dim_f[1], " x ", dim_f[2], " ", units, " image")
}
if (limitsize && any(dim >= 50)) {
stop("Dimensions exceed 50 inches (height and width are specified in '",
units, "' not pixels). If you're sure you a plot that big, use ",
"`limitsize = FALSE`.", call. = FALSE)
}
dim
}
plot_dev <<- function(device, filename, dpi = 300) {
if (is.function(device))
return(device)
eps <- function(...) {
grDevices::postscript(..., onefile = FALSE, horizontal = FALSE,
paper = "special")
}
devices <- list(
eps = eps,
ps = eps,
tex = function(...) grDevices::pictex(...),
pdf = function(..., version = "1.4") grDevices::pdf(..., version = version),
svg = function(...) grDevices::svg(...),
emf = function(...) grDevices::win.metafile(...),
wmf = function(...) grDevices::win.metafile(...),
png = function(...) grDevices::png(..., res = dpi, units = "in"),
jpg = function(...) grDevices::jpeg(..., res = dpi, units = "in"),
jpeg = function(...) grDevices::jpeg(..., res = dpi, units = "in"),
bmp = function(...) grDevices::bmp(..., res = dpi, units = "in"),
tiff = function(...) grDevices::tiff(..., res = dpi, units = "in")
)
if (is.null(device)) {
device <- tolower(tools::file_ext(filename))
}
if (!is.character(device) || length(device) != 1) {
stop("`device` must be NULL, a string or a function.", call. = FALSE)
}
dev <<- devices[[device]]
if (is.null(dev)) {
stop("Unknown graphics device '", device, "'", call. = FALSE)
}
dev
}
}
}
}
它基本上覆盖了 ggsave
并从开发版本创建了两个新函数。
执行函数后一切正常。
作为这个不幸的过渡期的临时解决方法,您可以重新实施 class 曾经在 gridExtra 中的 hack,
class(b) <- c("arrange","ggplot", class(b))
print.arrange <- function(x) grid.draw(x)
ggsave('test.pdf', b)
为我修复的是明确定义文件:
ggsave(file='test.pdf', b)