I've started using purrr:safely()
and purrr:quietly()
to tidily do things to nested data frames, like building a regression model or printing a ggplot. I quickly realised that I wanted to be able to see quickly when things were going wrong, and in which cases, so I built a couple of helpers, safely_status()
and quietly_status()
to scan the output quickly. Here's how they work:
library(tidyverse)
#> Warning: package 'ggplot2' was built under R version 3.5.1
#> Warning: package 'dplyr' was built under R version 3.5.1
# here they are: safeley_status() and quietley_status() ================================
safely_status = function(x, .prefix_err = 'Error:') {
map(x,
~ if (is.null(.$result)) {
paste(.prefix_err, .$error$message)
} else { 'OK' }) %>%
as_vector()
}
quietly_status = function(x, .prefix_err = 'Error:', .prefix_warn = 'Warning:',
.prefix_msg = 'Message:', .text_ok = 'OK') {
map(x,
~ if (is.null(.$warning) | is_empty(.$warning)) {
if (is.null(.$message) | is_empty(.$message)) {
.text_ok
} else { paste(.prefix_msg, .$message) }
} else { paste(.prefix_warn, .$warning) }) %>%
as_vector()
}
# example use =======================================================================
safe_log = safely(log)
quiet_log = quietly(log)
test =
# tidy up and trim down for the example
mtcars %>%
rownames_to_column(var = "car") %>%
as_data_frame() %>%
select(car, cyl, disp, wt) %>%
# spike some rows in cyl == 4 to make them fail
mutate(wt = case_when(
wt < 2 ~ -wt,
TRUE ~ wt)) %>%
# nest and do some operations quietly()
nest(-cyl) %>%
mutate(
qlog = map(data, ~ quiet_log(.$wt)),
qlog_status = quietly_status(qlog),
# optional: overwrite the "quiet" output with just successful results
qlog = map(qlog, "result"))
test
#> # A tibble: 3 x 4
#> cyl data qlog qlog_status
#> <dbl> <list> <list> <chr>
#> 1 6 <tibble [7 x 3]> <dbl [7]> OK
#> 2 4 <tibble [11 x 3]> <dbl [11]> Warning: NaNs produced
#> 3 8 <tibble [14 x 3]> <dbl [14]> OK
Created on 2018-10-26 by the reprex package (v0.2.0).
So this is nice, but there are some flaws: for one, you might get more than one of warnings, message, etc. I'm thinking of reworking this to a traffic-light system, where there are grey blocks (currently used for sparklines in tibble
) for each returned type (result, warning, message, output) and they're coloured (and, for colour-blind users, otherwise altered—say, full-height vs. quarter height) if they're present in the output.
So I have two questions:
- am I implementing this the best way in the first place (mapping over a list column and returning a string for each element), and
- Is
pillar
the right way to go about styling the outputted status column? Are there any good tutorials for usingpillar
this way?
Thanks