<p><div><div><div><div data-show-faces="false" data-height="21" data-width="100" data-layout="button_count" data-send="true" data-href="https://www.r-bloggers.com/collateral/"></div></div><div></div></div><div></div></div>
<div>
(This article was first published on <strong><a href="https://rensa.co/projects/collateral/"> James Goldie (rstats posts)</a></strong>, and kindly contributed to <a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers)</a> </div>
<p>Toward the end of my PhD analysis, I’ve started leaning on <a rel="nofollow" href="https://purrr.tidyverse.org/" target="_blank"><code>purrr</code></a> more and more to get analysis done on small multiples quickly and <em>safely</em>. Where before I might have used nested loops and potentially missed a lot of problems, I now split data frames out, build statistical models, extract model parameters and print plots all in one workflow.</p>
<p>This has incredible benefits for workflow: instead of having to track group identifiers across each output you produce, data and outputs and are linked to group identifiers by row, and you can do further tidying to summarise these complex outputs. You essentially have a summary of your analysis right there in the data frame.</p>
<p>In particular, <a rel="nofollow" href="https://purrr.tidyverse.org/reference/safely.html" target="_blank"><code>purrr::safely()</code> and <code>purrr::quietly()</code></a> wrap a number of R’s output and error handling systems, allowing you to push through errors as you iterate and capture them along with warnings, messages and other output. Instead of getting zero output until every group is behaving, you can get to the end of your analysis and then review to see what didn’t work out.</p>
<p>These two functions already lend themselves well to <code>map</code>ping, but since they return nested lists with each component of the output, it’s not always easy to tell until you burrow in to the returned column which groups returned output, which stopped with errors and which flagged other warnings or messages.</p>
<p>In response, I built the <a rel="nofollow" href="https://github.com/rensa/collateral" target="_blank"><code>collateral</code></a> package. Collateral provides two new <code>map</code> variants:</p>
<ul>
<li><code>map_safely()</code> wraps <code>safely()</code> and,</li>
<li><code>map_quietly()</code> wraps <code>quietly()</code>.</li>
</ul>
<p>As well as automatically wrapping these functions (so you can use them exactly as you would the vanilla <code>map()</code>), these functions style the resulting list (or list-column) using <code>pillar</code>—the same system that provides enhanced tibble output. You can scan down the column and see which mapped elements returned a result, which stopped with errors, and which returned warnings, messages or other output. If you’d like to inspect these kinds of output in more detail (for example, retrieve an error or read returned warnings), you can do so just as you would a manually mapped-and-wrapped function call, using components like <code>$result</code>, <code>$error</code> or <code>$warning</code>.</p>
<p>Here’s a quick example, using a safe version of <code>log</code> (as in the <a rel="nofollow" href="https://purrr.tidyverse.org/reference/safely.html#examples" target="_blank"><code>safely()</code> documentation</a>):</p>
<div>
<div>
<pre><code><span>library</span><span>(</span><span>tidyverse</span><span>)</span><span>
</span><span>library</span><span>(</span><span>collateral</span><span>)</span><span>
</span><span>test</span><span> </span><span>=</span><span>
</span><span># tidy up and trim down for the example</span><span>
</span><span>mtcars</span><span> </span><span>%>%</span><span>
</span><span>rownames_to_column</span><span>(</span><span>var</span><span> </span><span>=</span><span> </span><span>&quot;car&quot;</span><span>)</span><span> </span><span>%>%</span><span>
</span><span>as_data_frame</span><span>()</span><span> </span><span>%>%</span><span>
</span><span>select</span><span>(</span><span>car</span><span>,</span><span> </span><span>cyl</span><span>,</span><span> </span><span>disp</span><span>,</span><span> </span><span>wt</span><span>)</span><span> </span><span>%>%</span><span>
</span><span># spike some rows in cyl == 4 to make them fail</span><span>
</span><span>mutate</span><span>(</span><span>wt</span><span> </span><span>=</span><span> </span><span>dplyr</span><span>::</span><span>case_when</span><span>(</span><span>
</span><span>wt</span><span> </span><span></span><span> </span><span>2</span><span> </span><span>~</span><span> </span><span>-</span><span>wt</span><span>,</span><span>
</span><span>TRUE</span><span> </span><span>~</span><span> </span><span>wt</span><span>))</span><span> </span><span>%>%</span><span>
</span><span># nest and do some operations quietly()</span><span>
</span><span>nest</span><span>(</span><span>-</span><span>cyl</span><span>)</span><span> </span><span>%>%</span><span>
</span><span>mutate</span><span>(</span><span>qlog</span><span> </span><span>=</span><span> </span><span>map_quietly</span><span>(</span><span>data</span><span>,</span><span> </span><span>~</span><span> </span><span>log</span><span>(</span><span>.</span><span>$</span><span>wt</span><span>)))</span><span>
</span><span>test</span><span>
</span><span>#> # A tibble: 3 x 4</span><span>
</span><span>#> cyl data qlog</span><span>
</span><span>#> </span></code></pre></div></div>