2017-07-03 169 views
1

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

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那么新的矢量/列发生变异不会被计算。我无法使用管道工作tryCatch。任何想法或替代方法表示赞赏。

+0

当出现某种错误时,您期望的行为是什么? – Consistency

+0

我将循环遍历许多数据帧,所以每次函数都不起作用时,它会增加一个计数器:'func_2_errors = func_2_errors + 1'。如果两个函数都起作用,那么数据框应该有4列,如果一个函数失败了,数据框应该有3列,如果两者都失败了,它应该只有原始2。 –

回答

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)) 
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))