2017-07-03 2 views
1

J'ai deux fonctions similaires que je veux appliquer à une trame de données. Chaque fonction utilise deux vecteurs de la trame de données et crée un nouveau vecteur. Cependant, l'une des fonctions renvoie parfois des erreurs. En fin de compte, je vais utiliser ceci dans une boucle for et compter le nombre d'erreurs que chaque fonction donne (pour montrer qu'une fonction est meilleure que l'autre :-)). Cependant, je ne sais pas si je comprends tryCatch ou try assez bien pour utiliser avec des tuyaux. Voici un exemple d'une fois où une fonction échouerait.Utilisation de tryCatch avec des tubes Magrittr dans R

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

Quand j'Enroulez le muter avec un try puis le nouveau vecteur/colonne ne soit pas calculé. Je ne peux pas obtenir tryCatch pour travailler en utilisant les tuyaux. Toutes les pensées ou approches alternatives sont appréciées.

+0

Quel est le comportement souhaité en cas d'erreur? – Consistency

+0

Je vais parcourir de nombreuses trames de données, donc chaque fois qu'une fonction ne fonctionne pas, elle peut incrémenter un compteur: 'func_2_errors = func_2_errors + 1'. Si les deux fonctions fonctionnent, la trame de données devrait avoir 4 colonnes, si une fonction échoue, la trame de données devrait avoir 3 colonnes, si les deux échouent, elle devrait avoir juste l'original 2. –

Répondre

1

La fonction error_counting reçoit une fonction en tant que paramètre et retourne une fonction avec la même fonctionnalité et enregistre les temps d'erreur dans une liste appelée error_numbers. Et si une fonction échoue, la colonne correspondante de la trame de données sera 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

Peut-être quelque chose comme:

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