是否在dplyr的mutate中使用tryCatch?

byo*_*ess 4 exception-handling r dplyr mutate

dplyr中是否有任何异常处理机制mutate()?我的意思是捕获异常并处理异常的方法。

让我们假设我有一个函数在某些情况下会引发错误(在示例中,如果输入为负),为简单起见,我定义了该函数,但实际上,它将是某些R包中的函数。让我们假设此函数是矢量化的:

# function throwing an error
my_func <- function(x){
  if(x > 0) return(sqrt(x))
  stop('x must be positive')
}

my_func_vect <- Vectorize(my_func)
Run Code Online (Sandbox Code Playgroud)

现在,假设我要在内部使用此函数mutate()

如果在a中使用此函数mutate(),它将在第一个错误处停止并且不返回任何结果:

library(dplyr)
# dummy data
data <- data.frame(x = c(1, -1, 4, 9))
data %>% mutate(y = my_func_vect(x))
# Error in mutate_impl(.data, dots) : Evaluation error: x must be positive.
Run Code Online (Sandbox Code Playgroud)

有没有一种方法可以捕获错误,并NA在这种情况下执行某些操作(例如,返回),同时获取其他元素的结果?

我期望的结果是使用带有的循环可以实现的效果tryCatch(),即类似于以下内容:

y <- rep(NA_real_, length(data$x))
for(i in seq_along(data$x)) {
  tryCatch({
    y[i] <- my_func_vect(data$x[i])
  }, error = function(err){})
}
y
# Result is: 1 NA 2 4
Run Code Online (Sandbox Code Playgroud)

Lod*_*ert 5

您想单独评估每个发生的错误,也许您不应该使用矢量化函数。而是map从包中使用 -purrr这实际上与lapply此处相同。

如果在出现错误的情况下需要 NA 值,请创建一个函数来捕获错误以用于标准用途。

try_my_func <- function(x) {
  tryCatch(my_func(x), error = function(err){NA})
}
Run Code Online (Sandbox Code Playgroud)

然后,使用mutatemap

data %>% mutate(y = purrr::map(x, try_my_func))
   x  y
1  1  1
2 -1 NA
3  4  2
4  9  3
Run Code Online (Sandbox Code Playgroud)

或者类似地,如果您不想声明一个新函数。

data %>% mutate(y = purrr::map(x, ~ tryCatch(my_func(.), error = function(err){NA})))
Run Code Online (Sandbox Code Playgroud)

最后,如果您确实想使用矢量化函数,则可以map完全跳过该函数。但我个人从不使用,Vectorize所以我会用map.

data %>% mutate(y = Vectorize(try_my_func)(x))
Run Code Online (Sandbox Code Playgroud)


GGa*_*mba 5

我们也可以利用purrrsafely()possibly()功能。

purrr帮助中:

安全地:包装函数返回包含组件结果和错误的列表。一个值始终为NULL。

悄悄地:包装函数返回一个包含组件结果,输出,消息和警告的列表。

可能:每当发生错误时,包装函数都会使用默认值(否则)。

您不必将函数分别应用于每一行,这一事实并没有改变。

library(dplyr)
library(purrr)

# function throwing an error
my_func <- function(x){
  if(x > 0) return(sqrt(x))
  stop('x must be positive')
}

my_func_vect <- Vectorize(my_func)

# dummy data
data <- data.frame(x = c(1, -1, 4, 9))
Run Code Online (Sandbox Code Playgroud)

带有地图:

data %>% 
  mutate(y = map_dbl(x, ~possibly(my_func_vect, otherwise = NA_real_)(.x)))
#>    x  y
#> 1  1  1
#> 2 -1 NA
#> 3  4  2
#> 4  9  3
Run Code Online (Sandbox Code Playgroud)

使用rowwise()

data %>%
  rowwise() %>% 
  mutate(y = possibly(my_func_vect, otherwise = NA_real_)(x))
#> Source: local data frame [4 x 2]
#> Groups: <by row>
#> 
#> # A tibble: 4 x 2
#>       x     y
#>   <dbl> <dbl>
#> 1     1     1
#> 2    -1    NA
#> 3     4     2
#> 4     9     3
Run Code Online (Sandbox Code Playgroud)

其他功能在“数据框环境”中使用和应用起来有些困难,因为它们更适合于使用列表并返回。

reprex软件包(v0.2.0)创建于2018-05-15 。