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