Last active
April 26, 2017 16:44
-
-
Save stephlocke/dc72be42e39997bef894dfc95b67fd8a to your computer and use it in GitHub Desktop.
Foray into purrr for error handling
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
library(purrr) | |
library(dplyr) | |
#---- SETUP ----------------------------------------- | |
# A function that takes a reasonable amount of inputs | |
# and errors a bunch | |
doA <- function(letter, types, nonvar) { | |
if (letter >= "c") | |
stop("Error") | |
expand.grid(letter, types, nonvar) | |
} | |
# Some initial values | |
letter <- letters[1:3] | |
types <- LETTERS[1:3] | |
nonvar <- 1 | |
#---- THE PROBLEM ----------------------------------- | |
# With safe values, we can pass our variables | |
# as a list using `pmap` and then consolidate with | |
# `bind_rows`. | |
list(letter[-3], types[-3], nonvar) %>% | |
pmap(doA) %>% | |
dplyr::bind_rows() | |
# With erroring values, we get an error | |
list(letter, types, nonvar) %>% | |
pmap(doA) %>% | |
dplyr::bind_rows() | |
#---- MAKING IT WORK -------------------------------- | |
# Use the `safely` to produce list outputs for the | |
# function. Each element will contain a result and | |
# an error. | |
s_doA <- safely(doA) | |
# Use our safely version - no error! | |
list(letter, types, nonvar) %>% | |
pmap(s_doA) -> | |
int_result1 | |
# We need to process it though. Use `map` with a | |
# name to extract those bits from each element. | |
# As the empty results aren't interesting, use | |
# `discard` to drop them. | |
int_result1 %>% | |
map("result") %>% | |
discard( ~ is_null(.x)) %>% | |
dplyr::bind_rows() -> | |
result | |
# We can get the error messages where applicable | |
# for tracking which executions errored. We use | |
# `map` with a vector this time for a nested selection. | |
# Then we need to convert the NULL elements to something | |
# that will stick around in a vector. We use `map_if` | |
# to convert all NULLs to NAs. The `as_vector` then | |
# simplifies the results. | |
int_result1 %>% | |
map(c("error", "message")) %>% | |
map_if(is_null, function(x) | |
NA_character_) %>% | |
as_vector() -> | |
errors |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
library(purrr) | |
library(dplyr) | |
#---- SETUP ----------------------------------------- | |
generateTypeA_<-function(otherstuff){ | |
if(rnorm(1)>.75) stop(sample(LETTERS,1)) | |
data_frame(type="TypeA") | |
} | |
generateTypeA<-safely(generateTypeA_) | |
generateTypeB_<-function(otherstuff){ | |
if(rnorm(1)>.75) stop(sample(LETTERS,1)) | |
data_frame(type="TypeB") | |
} | |
generateTypeB<-safely(generateTypeB_) | |
generateTypeC_<-function(otherstuff){ | |
if(rnorm(1)>.75) stop(sample(LETTERS,1)) | |
data_frame(type="TypeC") | |
} | |
generateTypeC<-safely(generateTypeC_) | |
generateFragment_<-function(torun, otherstuff){ | |
torun %>% | |
invoke_map(otherstuff) | |
} | |
generateFragment<-safely(generateFragment_) | |
# Some initial values | |
torun <-c("generateTypeA", "generateTypeB", "generateTypeC") | |
otherstuff<-"blah" | |
list(torun, otherstuff) %>% | |
pmap(generateFragment) -> | |
int_result1 | |
int_result1 %>% | |
map("result") %>% | |
flatten() %>% | |
map_df("result") -> | |
result | |
int_result1 %>% | |
map("error") %>% | |
flatten -> | |
overallerrors | |
int_result1 %>% | |
map("result") %>% | |
flatten %>% | |
map_chr(c("error","message"), .null=NA_character_) -> | |
functionerrors | |
Courtesy of @jennybc
- Use the
crossing
function on L10 to make a tibble output - no pesky strings as factors! - Use
pmap_df
instead ofmap %>% bind_rows
in L23 - Use
compact
for more succinct NULL removal in L48 - Use the sneaky
.null
paramater in map_chr to do L60-61 in one step! (implemented in purrr 0.2.1)
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
L48 can become simply
discard(is_null) %>%