<p>I’ll be honest: the title is a bit misleading. I will not use <code>purrr</code> that much in this blog post. Actually, I will use one single <code>purrr</code> function, at the very end. I use <code>dplyr</code> much more. However Make ggplot2 purrr sounds better than Make ggplot dplyr or whatever the verb for <code>dplyr</code> would be.</p>
<p>Also, this blog post was inspired by a stackoverflow question and in particular one of the <a href="http://stackoverflow.com/a/29035145/1298051">answers</a>. So I don’t bring anything new to the table, but I found this stackoverflow answer so useful and so underrated (only 16 upvotes as I’m writing this!) that I wanted to write something about it.</p>
<p>Basically the idea of this blog post is to show how to create graphs using <code>ggplot2</code>, but by grouping by a factor variable beforehand. To illustrate this idea, let’s use the data from the <a href="http://www.rug.nl/ggdc/productivity/pwt/">Penn World Tables 9.0</a>. The easiest way to get this data is to install the package called <code>pwt9</code> with:</p>
<pre><code>install.packages(&quot;pwt9&quot;)</code></pre>
<p>and then load the data with:</p>
<pre><code>data(&quot;pwt9.0&quot;)</code></pre>
<p>Now, let’s load the needed packages. I am also using <code>ggthemes</code> which makes themeing your ggplots very easy. I’ll be making <a href="https://en.wikipedia.org/wiki/Edward_Tufte">Tufte</a>-style plots.</p>
<pre><code>library(ggplot2)
library(ggthemes)
library(dplyr)
library(purrr)
library(pwt9)</code></pre>
<p>First let’s select a list of countries:</p>
<pre><code>country_list &lt;- c(&quot;France&quot;, &quot;Germany&quot;, &quot;United States of America&quot;, &quot;Luxembourg&quot;, &quot;Switzerland&quot;, &quot;Greece&quot;)

small_pwt &lt;- pwt9.0 %>%
  filter(country %in% country_list)</code></pre>
<p>Let’s us also order the countries in the data frame as I have written them in <code>country_list</code>:</p>
<pre><code>small_pwt &lt;- small_pwt %>%
  mutate(country = factor(country, levels = country_list, ordered = TRUE))</code></pre>
<p>You might be wondering why this is important. At the end of the article, we are going to save the plots to disk. If we do not re-order the countries inside the data frame as in <code>country_list</code>, the name of the files will not correspond to the correct plots!</p>
<p>Now when you want to plot the same variable by countries, say <code>avh</code> (Average annual hours worked by persons engaged), the usual way to do this is with one of <code>facet_wrap()</code> or <code>facet_grid()</code>:</p>
<pre><code>ggplot(data = small_pwt) + theme_tufte() +
  geom_line(aes(y = avh, x = year)) +
  facet_wrap(~country)</code></pre>
<p></p>
<pre><code>ggplot(data = small_pwt) + theme_tufte() +
  geom_line(aes(y = avh, x = year)) +
  facet_grid(country~.)</code></pre>
<p></p>
<p>As you can see, for this particular example, <code>facet_grid()</code> is not very useful, but do notice its argument, <code>country~.</code>, which is different from <code>facet_wrap()</code>’s argument. This way, I get the graphs stacked horizontally. If I had used <code>facet_grid(~country)</code> the graphs would be side by side and completely unreadable.</p>
<p>Now, let’s go to the meat of this post: what if you would like to have one single graph for each country? You’d probably think of using <code>dplyr::group_by()</code> to form the groups and then the graphs. This is the way to go, but you also have to use <code>dplyr::do()</code>. This is because as far as I understand, <code>ggplot2</code> is not <code>dplyr</code>-aware, and using an arbitrary function with groups is only possible with <code>dplyr::do()</code>.</p>
<pre><code>plots &lt;- small_pwt %>%
  group_by(country) %>%
  do(plot = ggplot(data = .) + theme_tufte() +
       geom_line(aes(y = avh, x = year)) +
       ggtitle(unique(.$country)) +
       ylab(&quot;Year&quot;) +
       xlab(&quot;Average annual hours worked by persons engaged&quot;))</code></pre>
<p>If you know <code>dplyr</code> at least a little bit, the above lines should be easy for you to understand. But notice how we get the title of the graphs, with <code>ggtitle(unique(.$country))</code>, which was actually the point of the stackoverflow question. What might be surprising though, is the object that is created by this code. Let’s take a look at <code>plots</code>:</p>
<pre><code>print(plots)</code></pre>
<pre><code>## Source: local data frame [6 x 2]
## Groups: &lt;by row>
## 
## # A tibble: 6 × 2
##                    country     plot
## *                    &lt;ord>   &lt;list>
## 1                   France &lt;S3: gg>
## 2                  Germany &lt;S3: gg>
## 3 United States of America &lt;S3: gg>
## 4               Luxembourg &lt;S3: gg>
## 5              Switzerland &lt;S3: gg>
## 6                   Greece &lt;S3: gg></code></pre>
<p>As <code>dplyr::do()</code>’s documentation tells us, the return values get stored inside a list. And this is exactly what we get back; a list of plots! Lists are a very flexible and useful class, and you cannot spell list without <code>purrr</code> (at least not when you’re a ne<code>R</code>d).</p>
<p>Here are the final lines that use <code>purrr::map2()</code> to save all these plots at once inside your working directory:</p>
<pre><code>file_names &lt;- paste0(country_list, &quot;.pdf&quot;)

map2(file_names, plots$plot, ggsave)</code></pre>
<p>As I said before, if you do not re-order the countries inside the data frame, the names of the files and the plots will not match. Try running all the code without re-ordering, you’ll see!</p>
<p>I hope you found this post useful. You can follow me on <a href="https://www.twitter.com/brodriguesco">twitter</a> for blog updates.</p>