首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >错误:无法将ggsave添加到ggplot对象

错误:无法将ggsave添加到ggplot对象
EN

Stack Overflow用户
提问于 2021-06-16 13:27:03
回答 3查看 5.8K关注 0票数 10

我已经在Windows 10机器上安装了一个新的R安装程序,并且不能运行以下简单的程序:

代码语言:javascript
运行
复制
data.frame(a = rnorm(100), b = rnorm(100)) |> 
  ggplot(aes(a, b)) +
  ggsave("temp.png")

因为我得到了以下错误:

代码语言:javascript
运行
复制
Error: Can't add `ggsave("temp.png")` to a ggplot object.

我的会议信息是:

代码语言:javascript
运行
复制
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  

我已经将权限授予了我正在处理的目录,并在不同的目录中尝试使用RScript、RStudio和Pycharm控制台运行,始终存在相同的问题。

提前谢谢。

编辑:这曾经适用于ggplot2 3.3.3,它是对3.3.4的更新破坏了一切。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2021-06-16 13:34:24

您可以不再“添加”ggsave到一个ggplot添加-管道。

编辑:这是ggplot2-3.3.4的最新变化。如果您想要处理新的行为,前面的答案将保留在下面。如果您对此感到特别恼火,您可能会向ggplot2提交一个新的问题,建议他们要么(a)撤消中断的更改,要么(b)更好地记录非预期功能中的更改。

边注:在这个答案发布后的第二天,提交389b864包含了以下文本:“注意,作为一个副作用,一个非官方的黑客<ggplot object> + ggsave()不再工作(#4513)。”

(事实上,我不记得有文档表明+ ggsave(.)应该工作,所以对新问题的反应可能是他们不想为了放弃其他一些优雅的完整性而保留一个意想不到的“特性”。)

来自3.3.3至3.3.4 (对于save.R)的更改大多与保存文件的操作无关。但是,一个功能更改是来自ggsave的返回值。

代码语言:javascript
运行
复制
@@ -90,5 +98,5 @@ ggsave <- function(filename, plot = last_plot(),
   grid.draw(plot)

-  invisible()
+  invisible(filename)
 }

回顾一下,这是有意义的:ggplot2使用+-pipes的能力通常可以尝试添加NULL-like对象。也就是说,这是没有错误的:

代码语言:javascript
运行
复制
data.frame(a = rnorm(100), b = rnorm(100)) |>
  ggplot(aes(a, b)) +
  NULL

为什么NULL在这里有关联?因为上一个版本(3.3.3)的ggsaveinvisible()结尾,这是在无形地返回NULL。(在内部,ggplot2:::add_ggplotif (is.null(object)) return(p)开头,这解释了为什么工作。)

然而,随着对invisible(filename)的更改(实际上,imo更好一些),这实际上与

代码语言:javascript
运行
复制
data.frame(a = rnorm(100), b = rnorm(100)) |>
  ggplot(aes(a, b)) +
  "temp.png"

这没有道理,所以+-piping失败了。

ggplot2-3.3.3中,可以用黑客/丑陋代码复制此错误:

代码语言:javascript
运行
复制
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.

这非常接近您看到的错误(我相信)证明了我的观点:新的和改进的ggplot2-3.3.4返回一个字符串,这足以打破将ggsave添加到ggplot2对象的习惯模式。

如果要向ggplot2提交一个新的问题,那么我建议将其作为一个“特性请求”:如果invisible(filename)是一个+工作的类对象,那么可以保留之前的行为,同时仍然支持字符串返回。例如(完全未经测试):

代码语言:javascript
运行
复制
ggsave <- function(file, ...) {
  # .....
  class(filename) <- c("ggplot2_string", "character")
  invisible(filename)
}

然后将+.gg-logic扩展到实际用于字符串,可能类似于

代码语言:javascript
运行
复制
`+.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?")
    }
}

不,我不认为这是最好的方法,但这是一种方式,开放讨论。

你可以做四件事:

  1. 画出来,然后保存下来。它将显示在您的图形设备/窗格中。 data.frame(a = rnorm(100),b= rnorm(100)) |> ggplot(aes(a,b)) ggsave("temp.png")
  2. 保存到中间对象而不呈现,并保存如下: gg <- data.frame(a =r范数(100),b= rnorm(100) ) |> ggplot(aes(a,b)) ggsave("temp.png",temp.png= gg)
  3. 如果R-4.1,管道它执行plot=参数。虽然我还没有R-4.1,但基于评论,我相信虽然|>总是将前一个结果作为下一个调用的第一个参数传递,但是您可以通过命名file=参数来解决这个问题,这意味着R-4.1将传递给第一个可用的参数,在这个例子中,这个参数恰好是plot=,这正是我们所需要的。 data.frame(a = rnorm(100),b= rnorm(100)) |> ggplot(aes(a,b)) |> ggsave(file = "temp.png")
  4. 如果您使用的是magrittr管道,那么您可以更简洁地做同样的事情: 库(Magrittr)#或dplyr,如果您将它用于其他事情- data.frame(a = rnorm(100),b= rnorm(100)) %>% #或|> here ggplot(aes(a,b)) %>% #而不是|> -- ggsave("temp.png",%>%=。)
票数 22
EN

Stack Overflow用户

发布于 2021-06-16 13:30:42

只要移除加号。

代码语言:javascript
运行
复制
data.frame(a = rnorm(100), b = rnorm(100)) |> 
  ggplot(aes(a, b))

ggsave("temp.png")

ggsave具有默认输入last_plot()

票数 7
EN

Stack Overflow用户

发布于 2021-10-12 00:21:35

我不知道我的设置是否在某种程度上与其他设置不同,或者这是否只是我的ggsave代码被配置的方式,但它仍然对我起作用,同时也启动了错误。

中,托马斯说:

首先,虽然您将在v3.3.4中得到一个错误,但是这个图实际上被保存到一个文件中,因为该错误是在ggsave()的计算后抛出的。这意味着您可以通过将整个表达式放在try()块中来“修复”代码(请不要这样做)。

但你不需要做试块。我的代码块是:

代码语言:javascript
运行
复制
ggplot(stuff) +
  ggsave(paste0(today(), "_PlotName", ".png"),
         plot = last_plot(),
         device = "png", path = "", scale = 3.5, width = 8,
         height = 4, units = "in", dpi = 300, limitsize = TRUE)

可以推测,指定plot = last_plot()会使事情继续工作。但不要告诉任何人,以防他们拿走它;)

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68003633

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档