如何捕获在管道内评估 ggplot 对象时发生的错误?

How can I catch errors that occur when ggplot objects are evaluated within a pipe?

我正在根据原始 Covid 案例数据制作每日 powerpoint 幻灯片,今天,我们没有案例!太棒了,除了它打破了我的报告:-(

我生成 ggplots,并使用 officer 将它们放在 powerpoint 幻灯片上。 ggplot 错误仅在幻灯片创建管道内由官员评估时出现。

我可以在上游捕获错误,但是在幻灯片生成之前就这样做可以使代码更好,因为幻灯片生成过程是多层次的,尽管有错误但能够继续生成工件会很好.

Reprex 如下:

注意,错误不会出现在 R 3.6 中,可能是由于 scale_x_discrete 评估标签的方式发生了变化,但它会仍然有一个通用的方式来优雅地失败


library( stringr )
library(ggplot2)
library(officer)

data = structure(list(LGA = character(0), Sex = character(0)), row.names = integer(0), class = c("tbl_df",
"tbl", "data.frame"))


plot = ggplot( data, aes( LGA, Sex ) ) + 
  geom_point() +
  scale_x_discrete(labels = function(x) str_wrap(x, width = 15)) 

  read_pptx() %>%
    add_slide( )  %>%
    ph_with( plot, location=ph_location_type() )
#> Warning in rep(yes, length.out = len): 'x' is NULL so the result will be NULL
#> Error in ans[ypos] <- rep(yes, length.out = len)[ypos]: replacement has length zero

reprex package (v0.3.0)

于 2021-01-19 创建

看来我应该可以使用 purrr::possibly 来捕获错误,但它需要一个函数:

Error: Can't convert a `gg/ggplot` object to function

注:去掉了第二个例子

会话信息如下:


> sessionInfo()
R version 4.0.3 (2020-10-10)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows Server x64 (build 14393)

Matrix products: default

locale:
[1] LC_COLLATE=English_Australia.1252  LC_CTYPE=English_Australia.1252
[3] LC_MONETARY=English_Australia.1252 LC_NUMERIC=C
[5] LC_TIME=English_Australia.1252

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

other attached packages:
[1] purrr_0.3.4      officer_0.3.15   ggplot2_3.3.3    stringr_1.4.0
[5] nvimcom_0.9-92.3

loaded via a namespace (and not attached):
 [1] xml2_1.3.2       magrittr_2.0.1   tidyselect_1.1.0 munsell_0.5.0
 [5] uuid_0.1-4       colorspace_1.4-1 R6_2.5.0         rlang_0.4.8
 [9] dplyr_1.0.2      tools_4.0.3      grid_4.0.3       gtable_0.3.0
[13] withr_2.3.0      ellipsis_0.3.1   tibble_3.0.4     lifecycle_0.2.0
[17] crayon_1.3.4     zip_2.1.1        vctrs_0.3.4      glue_1.4.2
[21] stringi_1.5.3    compiler_4.0.3   pillar_1.4.6     generics_0.1.0
[25] scales_1.1.1     pkgconfig_2.0.3
>

我不能 100% 确定这是你的问题,因为我无法复制错误,但你可以尝试在 tryCatch() 中包装你的 ggplot 调用来处理错误:

tryCatch({
    plot <- ggplot( data, aes( LGA, Sex ) ) + 
      geom_point() +
      scale_x_discrete(labels = function(x) str_wrap(x, width = 15)) 

      read_pptx() %>%
        add_slide( )  %>%
        ph_with( plot, location=ph_location_type() )
    }, error = function(e) {
        message(as.character(e)) # exclude this line to return NULL quietly
        return(NULL)
    }
 )
 read_pptx() %>%
            add_slide( )  %>%
            ph_with( plot, location=ph_location_type() )

如果我在将 geom_point() 更改为 geom_pointesa() 的 ggplot 调用中故意出错,您将得到以下结果:

Error in geom_pointesa(): could not find function "geom_pointesa"

NULL

请注意,在这种情况下,ggplot 调用 returns NULL,同时打印一条错误消息以供审核。

sessionInfo() 下面:

R version 3.6.2 (2019-12-12)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 10 x64 (build 18362)

Matrix products: default

locale:
[1] LC_COLLATE=English_United States.1252  LC_CTYPE=English_United States.1252    LC_MONETARY=English_United States.1252 LC_NUMERIC=C                          
[5] LC_TIME=English_United States.1252    

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

other attached packages:
[1] officer_0.3.16 ggplot2_3.2.1  stringr_1.4.0 

loaded via a namespace (and not attached):
 [1] Rcpp_1.0.3       xml2_1.2.2       magrittr_2.0.1   tidyselect_1.1.0 munsell_0.5.0    uuid_0.1-4       colorspace_1.4-1 R6_2.5.0         rlang_0.4.9     
[10] dplyr_1.0.2      tools_3.6.2      grid_3.6.2       gtable_0.3.0     withr_2.3.0      ellipsis_0.3.1   lazyeval_0.2.2   tibble_2.1.3     lifecycle_0.2.0 
[19] crayon_1.3.4     zip_2.1.1        purrr_0.3.3      vctrs_0.3.5      glue_1.4.2       stringi_1.4.4    compiler_3.6.2   pillar_1.4.7     generics_0.1.0  
[28] scales_1.1.1     pkgconfig_2.0.3

错误发生在 ggplot_build() 构建地块时。通常你不会直接调用它,它是由显示对象的函数调用的,但你可以自己调用它。例如,

if (inherits(try(ggplot_build(plot)), "try-error")) 
  plot <- ggplot()

将用空白的情节替换糟糕的情节。