在R中使用带有Magrittr管道的tryCatch

时间:2017-07-03 15:43:05

标签: r try-catch tidyverse magrittr

我有两个类似的功能,我想应用于数据框。每个函数使用数据帧中的两个向量并创建一个新向量。但是,其中一个函数有时会返回错误。最后,我将在for循环中使用它并计算每个函数给出的错误数(表明一个函数比另一个函数更好:-))。但是,我不知道我是否理解tryCatchtry是否足以与管道一起使用。下面是一个函数失败的例子。

library(tidyverse)

# Function that works    
func_1 <- function(arg1, arg2) {
      arg1 + arg2
    }

# Function that errors
    func_2 <- function(arg1, arg2) {
      if(arg1 == 0) {error("Some Error")}
      else arg1 * arg2
    }

# Using the functions with pipes
    cars <- mtcars %>%
      filter(mpg > 18) %>%
      select("vs", "carb") %>%
      mutate(func1 = func_1(vs,carb)) %>%
      mutate(func1 = func_2(vs, carb))

当我用try包装mutate时,新的vector / column不会被计算出来。我无法让tryCatch使用管道工作。任何想法或替代方法都表示赞赏。

2 个答案:

答案 0 :(得分:1)

error_counting函数接收函数作为参数并返回具有相同功能的函数,并将错误时间记录在名为error_numbers的列表中。 如果一个函数失败,相应的数据框列将为NA

library(tidyverse)

# Function that works    
func_1 <- function(arg1, arg2) {
    arg1 + arg2
}

# Function that errors
func_2 <- function(arg1, arg2) {
    if (any(arg1 == 0)) {stop("Some Error")}
    else arg1 * arg2
}

error_numbers <- list()

error_counting <- function(f){
    force(f)
    fname <- as.character(substitute(f))
    error_numbers[[fname]] <<- 0
    count <- function(e){
        error_numbers[[fname]] <<- error_numbers[[fname]] + 1
        NA
    }
    function(...){
        tryCatch(f(...), error = count)
    }
}

e_func_1 <- error_counting(func_1)
e_func_2 <- error_counting(func_2)

# Using the functions with pipes
cars <- mtcars %>%
    filter(mpg > 18) %>%
    select(vs, carb) %>%
    mutate(func1 = e_func_1(vs,carb)) %>%
    mutate(func2 = e_func_2(vs, carb))

答案 1 :(得分:0)

也许是这样的:

library(tidyverse)

# Function that works    
func_1 <- function(arg1, arg2) {
  arg1 + arg2
}

# Function that errors
func_2 <- function(arg1, arg2) {
  if (arg1 == 0) { error("Some Error") }
  else arg1 * arg2
}

countingly <- function (.f, handle = uuid::UUIDgenerate(), otherwise = NULL, quiet = TRUE) {
  .f <- as_function(.f)
  function(...) {
    ret <- purrr:::capture_error(.f(...), otherwise)
    if (is.null(ret$result)) {
      error_track <<- c(error_track, list(f_hand = handle, f_err = ret$error))
      NA
    } else {
      ret$result
    }
  }
}

s_func_1 <- countingly(func_1, "f1")
s_func_2 <- countingly(func_2, "f2")

error_track <- list()

cars <- mtcars %>%
  filter(mpg > 18) %>%
  select("vs", "carb") %>%
  mutate(func1 = s_func_1(vs, carb)) %>%
  mutate(func2 = s_func_2(vs, carb))