0

I tried to write a function which would run other functions "safely". By safely here I just mean I don't want scripts to fall over if some plot functions fail. Simple example:

library(ggplot2)
library(purrr)

## function I thought I could use to run other functions safely
safe_plot <- function(.FUN, ...) {
  safe_fun <- purrr::possibly(.f = .FUN, otherwise = NULL)
  safe_fun(...)
}

## Simple plot function
plot_fun <- function(df) {
  df %>% 
    ggplot(aes(xvar, yvar)) +
    geom_point()
}

## Works for good data
some_data <- data.frame(xvar = 1:10, yvar = 1:10)
safe_plot(.FUN = plot_fun, df = some_data)

good

## Works here for data that is not defined:
> safe_plot(.FUN = plot_fun, df = not_defined)
NULL

## Falls over for an empty data frame
empty_data <- data.frame()
> safe_plot(.FUN = plot_fun, df = empty_data)
Error in FUN(X[[i]], ...) : object 'xvar' not found

What I would like is a generic function that I can pass plot functions to which - if an error occurs - won't stop a script. I know I could do the following for example:

## Simple plot function with check
plot_fun <- function(df) {
  if (nrow(df) > 0) {
    df %>%
      ggplot(aes(xvar, yvar)) +
      geom_point()
  }
}

But here I'm more interested in learning about why purrr::possibly did not catch the error and a perhaps a better way to go about this problem...assuming I don't care what may have caused an error.

Pete900
  • 2,016
  • 1
  • 21
  • 44

1 Answers1

0

You could directly use tryCatch.
In either cases, the reason for the error not being catched by possibly and eventually tryCatch is due to the lazy evaluation of print.ggplot which occurs outside tryCatch.
Solution is to force print() into tryCatch():

library(ggplot2)

safe_plot <- function(.FUN, ...) {
  tryCatch(print(.FUN(...)),error = function(e) NULL)
}

## Simple plot function
plot_fun <- function(df) {
  df %>% 
    ggplot(aes(xvar, yvar)) +
    geom_point() 
}


## Works for good data
some_data <- data.frame(xvar = 1:10, yvar = 1:10)
safe_plot(.FUN = plot_fun, df = some_data)
#> NULL

enter image description here


empty_data <- data.frame()
safe_plot(.FUN = plot_fun, df = empty_data)
#> NULL
Waldi
  • 39,242
  • 6
  • 30
  • 78
  • not sure why this answer doesn't seem to fullfill your needs, so that you posted [another question](https://stackoverflow.com/q/67637842/13513328) – Waldi May 25 '21 at 08:04