Home > Software design >  tryCatch() in across() fails when the error comes from another column
tryCatch() in across() fails when the error comes from another column

Time:07-08

I use across() and I want to put NA where the computation fails. I tried to use tryCatch() but can't make it work in my case, whereas there are situations where it works.

This works:

library(dplyr)
head(mtcars) %>% 
  mutate(
    across(
      all_of("drat"),
      function(x) tryCatch(blabla, error = function(e) NA) # create an intentional error for the example
    )
  )
#>                    mpg cyl disp  hp drat    wt  qsec vs am gear carb
#> Mazda RX4         21.0   6  160 110   NA 2.620 16.46  0  1    4    4
#> Mazda RX4 Wag     21.0   6  160 110   NA 2.875 17.02  0  1    4    4
#> Datsun 710        22.8   4  108  93   NA 2.320 18.61  1  1    4    1
#> Hornet 4 Drive    21.4   6  258 110   NA 3.215 19.44  1  0    3    1
#> Hornet Sportabout 18.7   8  360 175   NA 3.440 17.02  0  0    3    2
#> Valiant           18.1   6  225 105   NA 3.460 20.22  1  0    3    1

But this doesn't:

library(dplyr)
head(mtcars) %>% 
  mutate(
    across(
      all_of("drat"),
      function(x) tryCatch(x[which(mpg == 10000)], error = function(e) NA) # create an intentional error for the example
    )
  )
#> Error in `mutate()`:
#> ! Problem while computing `..1 = across(...)`.
#> Caused by error in `across()`:
#> ! Problem while computing column `drat`.

Created on 2022-07-07 by the reprex package (v2.0.1)

I thought tryCatch() was supposed to catch any error. Why doesn't it work in the second situation? How to fix it?

Note: I need to use across() in my real situation (even if it's not truly needed in the examples)

CodePudding user response:

The problem isn't the tryCatch because the code you run doesn't trigger an error. Basically you are running

foo <- function(x) tryCatch(x[which(mtcars$mpg==10000)], error = function(e) NA))
foo(mtcars$drat)
# numeric(0)

And notice that no error is triggered. That expression simply returns numeric(0). And the problem is that the function needs to return a value with a non-zero length. So the error is happening after your tryCatch code runs and dplyr is trying to assign the value back into the data.frame. You will need to handle the case where no values are found separately. Perhaps

head(mtcars) %>% 
  mutate(
    across(
      all_of("drat"),
      function(x) {
        matches <- mpg == 10000
        if (any(matches)) x[which(matches)] else NA
      }
    )
  )

CodePudding user response:

It looks like you just need to reference mpg with x:

library(dplyr)

head(mtcars) %>% 
  mutate(
    across(
      all_of("drat"),
      function(x) tryCatch(x[which(x$mpg == 10000)], error = function(e) NA) # create an intentional error for the example
    )
  )
#>                    mpg cyl disp  hp drat    wt  qsec vs am gear carb
#> Mazda RX4         21.0   6  160 110   NA 2.620 16.46  0  1    4    4
#> Mazda RX4 Wag     21.0   6  160 110   NA 2.875 17.02  0  1    4    4
#> Datsun 710        22.8   4  108  93   NA 2.320 18.61  1  1    4    1
#> Hornet 4 Drive    21.4   6  258 110   NA 3.215 19.44  1  0    3    1
#> Hornet Sportabout 18.7   8  360 175   NA 3.440 17.02  0  0    3    2
#> Valiant           18.1   6  225 105   NA 3.460 20.22  1  0    3    1
  • Related