我已经在 Windows 10 机器上设置了全新的 R 安装,并且无法运行像以下这样简单的东西:
data.frame(a = rnorm(100), b = rnorm(100)) |>
ggplot(aes(a, b)) +
ggsave("temp.png")
Run Code Online (Sandbox Code Playgroud)
因为我收到以下错误:
Error: Can't add `ggsave("temp.png")` to a ggplot object.
Run Code Online (Sandbox Code Playgroud)
我的会话信息是:
R version 4.1.0 (2021-05-18)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows >= 8 x64 (build 9200)
Matrix products: default
locale:
[1] LC_COLLATE=Catalan_Spain.1252 LC_CTYPE=Catalan_Spain.1252 LC_MONETARY=Catalan_Spain.1252 LC_NUMERIC=C
[5] LC_TIME=Catalan_Spain.1252
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] ggplot2_3.3.4 dplyr_1.0.6
loaded via a namespace (and not attached):
[1] magrittr_2.0.1 tidyselect_1.1.1 munsell_0.5.0 colorspace_2.0-1 R6_2.5.0 rlang_0.4.11 fansi_0.5.0 tools_4.1.0
[9] grid_4.1.0 data.table_1.14.0 gtable_0.3.0 utf8_1.2.1 withr_2.4.2 ellipsis_0.3.2 digest_0.6.27 tibble_3.1.2
[17] lifecycle_1.0.0 crayon_1.4.1 purrr_0.3.4 farver_2.1.0 vctrs_0.3.8 glue_1.4.2 labeling_0.4.2 compiler_4.1.0
[25] pillar_1.6.1 generics_0.1.0 scales_1.1.1 pkgconfig_2.0.3
Run Code Online (Sandbox Code Playgroud)
我已授予我正在处理的目录的权限,并在不同的目录中尝试并使用 RScript、RStudio 和 Pycharm R 控制台运行,但始终遇到相同的问题。
提前致谢。
编辑:这曾经适用于 ggplot2 3.3.3,这是对 3.3.4 的更新破坏了事情。
r2e*_*ans 12
您不能再“添加”ggsave
到 ggplot 添加管道。
编辑:这是ggplot2-3.3.4
. 如果您想解决新行为,则将在下面保留先前的答案。如果您对此特别恼火,您可能会提交一个新问题以ggplot2
建议他们 (a) 撤消破坏性更改,或 (b) 更好地记录意外功能中的更改。
(实际上,我不记得看过表明+ ggsave(.)
应该可行的文档,因此对新问题的回应可能是他们不想为了放弃其他一些优雅的完整性而保留意外的“功能”。)
从3.3.3 到 3.3.4 (for save.R
)的更改大多与保存文件的行为无关。但是,一项功能更改是来自 的返回值ggsave
:
@@ -90,5 +98,5 @@ ggsave <- function(filename, plot = last_plot(),
grid.draw(plot)
- invisible()
+ invisible(filename)
}
Run Code Online (Sandbox Code Playgroud)
回想起来,这是有道理的:ggplot2
使用+
-pipes的能力在尝试添加 -like 对象时往往没问题NULL
。也就是说,这可以正常工作:
data.frame(a = rnorm(100), b = rnorm(100)) |>
ggplot(aes(a, b)) +
NULL
Run Code Online (Sandbox Code Playgroud)
为什么NULL
在这里是相关的?因为之前的 (3.3.3) 版本以ggsave
结束invisible()
,无形中又返回了NULL
。(在内部,ggplot2:::add_ggplot
以 开头if (is.null(object)) return(p)
,这解释了为什么会这样。)
invisible(filename)
然而,随着更改为(imo,实际上更好一点),这实际上与
data.frame(a = rnorm(100), b = rnorm(100)) |>
ggplot(aes(a, b)) +
"temp.png"
Run Code Online (Sandbox Code Playgroud)
这是没有意义的,所以+
-piping 失败了。
在 中ggplot2-3.3.3
,您可以使用黑客/丑陋的代码复制此错误:
data.frame(a = rnorm(100), b = rnorm(100)) |>
ggplot(aes(a, b)) +
{ ggsave("temp.png"); "temp.png"; }
# Error: Can't add `{` to a ggplot object.
# * Can't add ` ggsave("temp.png")` to a ggplot object.
# * Can't add ` "temp.png"` to a ggplot object.
# * Can't add `}` to a ggplot object.
Run Code Online (Sandbox Code Playgroud)
这足够接近你看到的错误(我相信)证明了我的观点:新的和改进的 ggplot2-3.3.4 正在返回一个字符串,这足以打破你添加ggsave
到 ggplot2 的习惯模式目的。
如果您要向 ggplot2 提交一个新问题,那么我建议您将其定义为“功能请求”:如果它invisible(filename)
是一个适用的类对象+
,则可以保留以前的行为,同时仍支持字符串-返回。例如(完全未经测试):
ggsave <- function(file, ...) {
# .....
class(filename) <- c("ggplot2_string", "character")
invisible(filename)
}
Run Code Online (Sandbox Code Playgroud)
然后扩展+.gg
-logic 以实际处理字符串,可能类似于
`+.gg` <- function (e1, e2) {
if (missing(e2)) {
abort("Cannot use `+.gg()` with a single argument. Did you accidentally put + on a new line?")
}
if (inherits(e2, "ggplot2_string")) {
e2 <- NULL
e2name <- "NULL"
} else {
e2name <- deparse(substitute(e2))
}
if (is.theme(e1))
add_theme(e1, e2, e2name)
else if (is.ggplot(e1))
add_ggplot(e1, e2, e2name)
else if (is.ggproto(e1)) {
abort("Cannot add ggproto objects together. Did you forget to add this object to a ggplot object?")
}
}
Run Code Online (Sandbox Code Playgroud)
不,我不认为这是最好的方式,但这是一种方式,可以讨论。
你可以做的四件事:
绘制它,然后保存它。它将显示在您的图形设备/窗格中。
data.frame(a = rnorm(100), b = rnorm(100)) |>
ggplot(aes(a, b))
ggsave("temp.png")
Run Code Online (Sandbox Code Playgroud)
保存到不渲染的中间对象,并保存:
gg <- data.frame(a = rnorm(100), b = rnorm(100)) |>
ggplot(aes(a, b))
ggsave("temp.png", plot = gg)
Run Code Online (Sandbox Code Playgroud)
如果 R-4.1,管道它做plot=
参数。虽然我还没有 R-4.1,但根据评论,我相信 while|>
总是将前一个结果作为下一个调用的第一个参数传递,您可以通过命名file=
参数来解决这个问题,这意味着 R-4.1将传递给第一个可用参数,它(在这种情况下)恰好plot=
是我们需要的。
data.frame(a = rnorm(100), b = rnorm(100)) |>
ggplot(aes(a, b)) |>
ggsave(file = "temp.png")
Run Code Online (Sandbox Code Playgroud)
如果您使用的是 magrittr 管道,那么您可以更简洁地做同样的事情:
library(magrittr) # or dplyr, if you're using it for other things
data.frame(a = rnorm(100), b = rnorm(100)) %>% # or |> here
ggplot(aes(a, b)) %>% # but not |> here
ggsave("temp.png", plot = .)
Run Code Online (Sandbox Code Playgroud)
只需删除加号即可。
data.frame(a = rnorm(100), b = rnorm(100)) |>
ggplot(aes(a, b))
ggsave("temp.png")
Run Code Online (Sandbox Code Playgroud)
ggsave 有一个默认输入last_plot()