2017-07-03 114 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))