<p>In my last two posts I have been writing about the task of using R to<br>
“drive” MS Excel. The first post focused on just the basic mechanics<br>
of getting my colleague what she needed. The second post picked up with<br>
some ugly inefficient code and made it better using <code>lapply</code> and a <code>for<br>
loop</code>, just good old fashioned automation (the thing that computers<br>
excel at). Today I’ll take it another step and show how to produce the<br>
same graphs in <code>R</code> using <code>ggplot2</code> as well as how to write some simple<br>
functions to make your programming life easier.</p>
<h2>Background and catch-up</h2>
<p>My colleague wanted to be able to do some simple analysis around health<br>
care using the <a rel="nofollow" href="https://www.cdc.gov/" target="_blank">Centers for Disease Control and<br>
Prevention</a>, <a rel="nofollow" href="https://www.cdc.gov/nchs/index.htm" target="_blank">National Center for Health<br>
Statistics</a>, <a rel="nofollow" href="https://www.cdc.gov/nchs/nhis/nhis_2016_data_release.htm" target="_blank">National Health<br>
Interview<br>
Survey</a>. They<br>
wanted a series of cross tabulated sets of summary data for variable<br>
pairings (for example whether or not the respondent had a formal health<br>
care provider by region of the country). They wanted one Excel<br>
“workbook” with 12 worksheets, each one of which was the summary of<br>
counts for a pair of variables. From there they could use Excel’s native<br>
plotting tools to make the graphs they needed.</p>
<p>You can <a rel="nofollow" href="https://ibecav.github.io/Functionalize/" target="_blank">review everything that happened in the first<br>
post</a>, <a rel="nofollow" href="https://ibecav.github.io/RtoExcel/" target="_blank">as well as the<br>
second</a> (<strong>which I strongly<br>
recommend</strong>), or you can start on this page. To join us in progress make<br>
sure you load the right libraries and grab the dataset we wound up with<br>
from our earlier work – it’s called <code>OfInterest</code>. it represents the<br>
variables of interest for us after winnowing down a very large dataset<br>
we got from the <strong>CDC</strong>.</p>
<div>
<div>
<pre><code><span>knitr</span><span>::</span><span>opts_chunk</span><span>$</span><span>set</span><span>(</span><span>echo</span><span> </span><span>=</span><span> </span><span>TRUE</span><span>,</span><span> </span><span>warning</span><span> </span><span>=</span><span> </span><span>FALSE</span><span>)</span><span>
</span><span>library</span><span>(</span><span>dplyr</span><span>)</span><span>
</span></code></pre>
</div>
</div>
<div>
<div>
<pre><code>## 
## Attaching package: 'dplyr'

## The following objects are masked from 'package:stats':
## 
##     filter, lag

## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
</code></pre>
</div>
</div>
<div>
<div>
<pre><code><span>library</span><span>(</span><span>ggplot2</span><span>)</span><span>
</span><span>theme_set</span><span>(</span><span>theme_bw</span><span>())</span><span> </span><span># set theme to my personal preference</span><span>
</span><span># install.packages(&quot;openxlsx&quot;)</span><span>
</span><span>require</span><span>(</span><span>openxlsx</span><span>)</span><span>
</span></code></pre>
</div>
</div>
<div>
<div>
<pre><code>## Loading required package: openxlsx
</code></pre>
</div>
</div>
<div>
<div>
<pre><code><span>OfInterest</span><span> </span><span>&lt;-</span><span> </span><span>read.csv</span><span>(</span><span>&quot;ofinterest.csv&quot;</span><span>)</span><span>
</span><span>### OfInterest &lt;-read.csv(&quot;https://raw.githubusercontent.com/ibecav/ibecav.github.io/master/Rmdfiles/ofinterest.csv&quot;) available through Github about 9Mb</span><span>
</span><span>str</span><span>(</span><span>OfInterest</span><span>)</span><span>
</span></code></pre>
</div>
</div>
<div>
<div>
<pre><code>## 'data.frame':    103789 obs. of  9 variables:
##  $ AGE      : Factor w/ 3 levels &quot;19 to 60&quot;,&quot;Less than 18&quot;,..: 1 1 1 2 2 1 1 1 3 1 ...
##  $ REGION   : Factor w/ 4 levels &quot;Midwest&quot;,&quot;Northeast&quot;,..: 3 4 4 4 4 4 3 3 4 3 ...
##  $ SEX      : Factor w/ 2 levels &quot;Female&quot;,&quot;Male&quot;: 2 1 2 2 1 1 1 2 2 2 ...
##  $ EDUCATION: Factor w/ 3 levels &quot;Bachelor's degree or higher&quot;,..: 3 2 1 2 NA 1 2 2 1 3 ...
##  $ EARNINGS : Factor w/ 3 levels &quot;$01-$34,999&quot;,..: 1 2 2 NA NA 3 1 NA 2 3 ...
##  $ PDMED12M : Factor w/ 2 levels &quot;No&quot;,&quot;Yes&quot;: 1 2 1 1 1 1 1 1 1 1 ...
##  $ PNMED12M : Factor w/ 2 levels &quot;No&quot;,&quot;Yes&quot;: 1 1 1 1 1 1 1 1 1 1 ...
##  $ NOTCOV   : Factor w/ 2 levels &quot;Covered&quot;,&quot;Not covered&quot;: 1 1 1 1 1 1 1 1 1 1 ...
##  $ MEDBILL  : Factor w/ 2 levels &quot;No&quot;,&quot;Yes&quot;: 1 2 2 2 2 1 1 1 1 1 ...
</code></pre>
</div>
</div>
<h2>Where we left off</h2>
<p>Yesterday we left off accomplishing this workflow:</p>
<ol>
<li>Create a new empty workbook object <code>wb &lt;- createWorkbook()</code> <strong>once</strong></li>
<li>Invent a name for the <strong>tab</strong> or worksheet inside the workbook<br>
<code>NameofSheet</code> <strong>12 times</strong></li>
<li>Make a <code>table</code> for a pair of variables like <code>TheData</code> <strong>12 times</strong></li>
<li>Add a worksheet (tab) into the workbook <code>addWorksheet</code> <strong>12 times</strong></li>
<li>Write the table we made onto the worksheet with <code>writeData</code> <strong>12<br>
times</strong></li>
<li>Save the workbook with the 12 sheets in it <strong>once</strong></li>
</ol>
<p></p>
<div>
<div>
<pre><code><span># put our variables into two lists</span><span>
</span><span>depvars</span><span> </span><span>&lt;-</span><span> </span><span>list</span><span>(</span><span>Coverage</span><span> </span><span>=</span><span> </span><span>OfInterest</span><span>$</span><span>NOTCOV</span><span>,</span><span> </span><span>ProbPay</span><span> </span><span>=</span><span> </span><span>OfInterest</span><span>$</span><span>MEDBILL</span><span>,</span><span> </span><span>CareDelay</span><span> </span><span>=</span><span> </span><span>OfInterest</span><span>$</span><span>PDMED12M</span><span>,</span><span> </span><span>NeedNotGet</span><span> </span><span>=</span><span> </span><span>OfInterest</span><span>$</span><span>PNMED12M</span><span>)</span><span>
</span><span>indvars</span><span> </span><span>&lt;-</span><span> </span><span>list</span><span>(</span><span>Education</span><span> </span><span>=</span><span> </span><span>OfInterest</span><span>$</span><span>EDUCATION</span><span>,</span><span> </span><span>Earnings</span><span> </span><span>=</span><span> </span><span>OfInterest</span><span>$</span><span>EARNINGS</span><span>,</span><span> </span><span>Age</span><span> </span><span>=</span><span> </span><span>OfInterest</span><span>$</span><span>AGE</span><span>)</span><span>
</span><span># Use lapply to make a list that contains the tables</span><span>
</span><span>TablesList</span><span> </span><span>&lt;-</span><span> </span><span>lapply</span><span>(</span><span>depvars</span><span>,</span><span> </span><span>function</span><span> </span><span>(</span><span>x</span><span>)</span><span> </span><span>lapply</span><span>(</span><span>indvars</span><span>,</span><span> </span><span>function</span><span> </span><span>(</span><span>y</span><span>)</span><span> </span><span>table</span><span>(</span><span>y</span><span>,</span><span>x</span><span>)))</span><span>
</span><span>## Create a new empty workbook</span><span>
</span><span>wb</span><span> </span><span>&lt;-</span><span> </span><span>createWorkbook</span><span>()</span><span>
</span><span>## nested for loop</span><span>
</span><span>for</span><span> </span><span>(</span><span>j</span><span> </span><span>in</span><span> </span><span>seq_along</span><span>(</span><span>TablesList</span><span>))</span><span> </span><span>{</span><span> </span><span>#top list with depvars</span><span>
</span><span>for</span><span> </span><span>(</span><span>i</span><span> </span><span>in</span><span> </span><span>seq_along</span><span>(</span><span>TablesList</span><span>[[</span><span>j</span><span>]]))</span><span> </span><span>{</span><span> </span><span>#for each depvar walk the indvars</span><span>
</span><span>TheData</span><span> </span><span>&lt;-</span><span> </span><span>TablesList</span><span>[[</span><span>j</span><span>]][[</span><span>i</span><span>]]</span><span>
</span><span>NameofSheet</span><span> </span><span>&lt;-</span><span> </span><span>paste0</span><span>(</span><span>names</span><span>(</span><span>TablesList</span><span>[</span><span>j</span><span>]),</span><span> </span><span>&quot;By&quot;</span><span>,</span><span> </span><span>names</span><span>(</span><span>TablesList</span><span>[[</span><span>j</span><span>]][</span><span>i</span><span>]))</span><span>
</span><span>addWorksheet</span><span>(</span><span>wb</span><span> </span><span>=</span><span> </span><span>wb</span><span>,</span><span> </span><span>sheetName</span><span> </span><span>=</span><span> </span><span>NameofSheet</span><span>)</span><span>
</span><span>writeData</span><span>(</span><span>wb</span><span> </span><span>=</span><span> </span><span>wb</span><span>,</span><span> </span><span>sheet</span><span> </span><span>=</span><span> </span><span>NameofSheet</span><span>,</span><span> </span><span>x</span><span> </span><span>=</span><span> </span><span>TheData</span><span>,</span><span> </span><span>borders</span><span> </span><span>=</span><span> </span><span>&quot;n&quot;</span><span>)</span><span>
</span><span>}</span><span>
</span><span>}</span><span>
</span><span>## Save our new workbook</span><span>
</span><span>saveWorkbook</span><span>(</span><span>wb</span><span>,</span><span> </span><span>&quot;newversion.xlsx&quot;</span><span>,</span><span> </span><span>overwrite</span><span> </span><span>=</span><span> </span><span>TRUE</span><span>)</span><span> </span><span>## save to working directory</span><span>
</span></code></pre>
</div>
</div>
<p>At this juncture my colleague is happy. She has her workbook nicely<br>
organized and she can do what she needs to do in MS Excel. I’m sure that<br>
included making some graphs as well. If you’re interested the <code>openxlsx</code><br>
package even includes facilities for inserting ggplot graphics onto the<br>
work sheets.</p>
<h2>Better plotting through R</h2>
<p>One thing I wanted to explore was just automating the process of<br>
plotting the data in <code>R</code> as much as I could. Basic plotting was a<br>
breeze, no need to create special lists of tables, just pipe <code>%>%</code><br>
things straight from the dataframe into ggplot. Here are at least three<br>
possible bar or column plots of <code>EDUCATION</code> and <code>NOTCOV</code> with very<br>
little effort.</p>
<div>
<div>
<pre><code><span>### with dplyr and ggplot</span><span>
</span><span>OfInterest</span><span> </span><span>%>%</span><span>
</span><span>filter</span><span>(</span><span>!</span><span>is.na</span><span>(</span><span>EDUCATION</span><span>),</span><span> </span><span>!</span><span>is.na</span><span>(</span><span>NOTCOV</span><span>))</span><span> </span><span>%>%</span><span>
</span><span>group_by</span><span>(</span><span>EDUCATION</span><span>,</span><span>NOTCOV</span><span>)</span><span> </span><span>%>%</span><span>
</span><span>count</span><span>()</span><span> </span><span>%>%</span><span>
</span><span>ggplot</span><span>(</span><span>aes</span><span>(</span><span>fill</span><span>=</span><span>EDUCATION</span><span>,</span><span> </span><span>y</span><span>=</span><span>n</span><span>,</span><span> </span><span>x</span><span>=</span><span>NOTCOV</span><span>))</span><span> </span><span>+</span><span>
</span><span>geom_bar</span><span>(</span><span>position</span><span>=</span><span>&quot;dodge&quot;</span><span>,</span><span> </span><span>stat</span><span>=</span><span>&quot;identity&quot;</span><span>)</span><span>
</span></code></pre>
</div>
</div>
<p><img alt="" src="https://i2.wp.com/ibecav.github.io/images/makeplots1-1.png?w=456" data-recalc-dims="1"></p>
<div>
<div>
<pre><code><span>OfInterest</span><span> </span><span>%>%</span><span>
</span><span>filter</span><span>(</span><span>!</span><span>is.na</span><span>(</span><span>EDUCATION</span><span>),</span><span> </span><span>!</span><span>is.na</span><span>(</span><span>NOTCOV</span><span>))</span><span> </span><span>%>%</span><span>
</span><span>group_by</span><span>(</span><span>EDUCATION</span><span>,</span><span>NOTCOV</span><span>)</span><span> </span><span>%>%</span><span>
</span><span>count</span><span>()</span><span> </span><span>%>%</span><span>
</span><span>ggplot</span><span>(</span><span>aes</span><span>(</span><span>fill</span><span>=</span><span>EDUCATION</span><span>,</span><span> </span><span>y</span><span>=</span><span>n</span><span>,</span><span> </span><span>x</span><span>=</span><span>NOTCOV</span><span>))</span><span> </span><span>+</span><span>
</span><span>geom_bar</span><span>(</span><span>stat</span><span>=</span><span>&quot;identity&quot;</span><span>)</span><span>
</span></code></pre>
</div>
</div>
<p><img alt="" src="https://i2.wp.com/ibecav.github.io/images/makeplots1-2.png?w=456" data-recalc-dims="1"></p>
<div>
<div>
<pre><code><span>OfInterest</span><span> </span><span>%>%</span><span>
</span><span>filter</span><span>(</span><span>!</span><span>is.na</span><span>(</span><span>EDUCATION</span><span>),</span><span> </span><span>!</span><span>is.na</span><span>(</span><span>NOTCOV</span><span>))</span><span> </span><span>%>%</span><span>
</span><span>group_by</span><span>(</span><span>EDUCATION</span><span>,</span><span>NOTCOV</span><span>)</span><span> </span><span>%>%</span><span>
</span><span>count</span><span>()</span><span> </span><span>%>%</span><span>
</span><span>ggplot</span><span>(</span><span>aes</span><span>(</span><span>fill</span><span>=</span><span>EDUCATION</span><span>,</span><span> </span><span>y</span><span>=</span><span>n</span><span>,</span><span> </span><span>x</span><span>=</span><span>NOTCOV</span><span>))</span><span> </span><span>+</span><span>
</span><span>geom_bar</span><span>(</span><span>stat</span><span>=</span><span>&quot;identity&quot;</span><span>,</span><span> </span><span>position</span><span>=</span><span>&quot;fill&quot;</span><span>)</span><span>
</span></code></pre>
</div>
</div>
<p><img alt="" src="https://i1.wp.com/ibecav.github.io/images/makeplots1-3.png?w=456" data-recalc-dims="1"></p>
<p><strong>Note that with our original choice of using the <code>table</code> command to<br>
create the cross tabulation that the <code>NA</code>s were silently discarded. With<br>
<code>dplyr</code> if we don’t <code>filter</code> them out we will see them plotted which may<br>
or may not be what you want substantively!</strong></p>
<p><strong>From this point forward I’m going to print the plots in a smaller<br>
size. I’m doing that via RMarkdown and it won’t happen automatically for<br>
you.</strong></p>
<p>Here’s the graph with the NA’s left in place.</p>
<div>
<div>
<pre><code><span>OfInterest</span><span> </span><span>%>%</span><span>
</span><span># filter(!is.na(EDUCATION), !is.na(NOTCOV)) %>%</span><span>
</span><span>group_by</span><span>(</span><span>EDUCATION</span><span>,</span><span>NOTCOV</span><span>)</span><span> </span><span>%>%</span><span>
</span><span>count</span><span>()</span><span> </span><span>%>%</span><span>
</span><span>ggplot</span><span>(</span><span>aes</span><span>(</span><span>fill</span><span>=</span><span>EDUCATION</span><span>,</span><span> </span><span>y</span><span>=</span><span>n</span><span>,</span><span> </span><span>x</span><span>=</span><span>NOTCOV</span><span>))</span><span> </span><span>+</span><span>
</span><span>geom_bar</span><span>(</span><span>stat</span><span>=</span><span>&quot;identity&quot;</span><span>,</span><span> </span><span>position</span><span>=</span><span>&quot;fill&quot;</span><span>)</span><span>
</span></code></pre>
</div>
</div>
<p><img alt="" src="https://i0.wp.com/ibecav.github.io/images/makeplots2-1.png?w=456" data-recalc-dims="1"></p>
<p>I’ll leave it up to you, the reader, to decide which graph communicates<br>
any points you want to make about the data. I also acknowledge that at<br>
this point I’ve done a poor job of labeling the plot properly. We’ll<br>
come back to that later. For now I want you to focus on a couple of<br>
areas that are ripe for automation. One is improving our ability to pass<br>
multiple variables and get multiple plots. Let’s avoid cutting and<br>
pasting the code repeatedly shall we? We could also look at letting our<br>
user choose which plot type they prefer.</p>
<p>Now, I happen to love using <code>dplyr</code>, it is so elegant, and the syntax,<br>
plus piping, is just a joy to work with. But the downside is that it was<br>
originally designed to be used at the command prompt interactively. It<br>
makes heavy use of <strong>non standard evaluation</strong> <code>NSE</code> which <a rel="nofollow" href="https://adv-r.hadley.nz/meta.html#" target="_blank">makes it<br>
tricky to program functions with</a>.<br>
Not impossible, but tricky. <a rel="nofollow" href="http://dplyr.tidyverse.org/articles/programming.html" target="_blank">Hadley Wickham has written about it<br>
extensively</a> and<br>
the <a rel="nofollow" href="https://stackoverflow.com/questions/27975124/pass-arguments-to-dplyr-functions/44594223" target="_blank">Stack<br>
Overflow</a><br>
is full of questions about it, so I’m not sure I’m the person to explain<br>
it. But I can show a practical example of how to use it. And if you’re<br>
like me that is sometimes very helpful.</p>
<p>You would think (if you knew <a rel="nofollow" href="https://adv-r.hadley.nz/functional-programming.html" target="_blank">even a little bit about functions in<br>
<code>R</code></a>) that all we<br>
would have to do is take our code snippet from above and do some<br>
substitution… After all it’s just simple substitution right? Trust me it<br>
won’t work. Nor will any amount of traditional quoting, e.g. single<br>
quotes, double quotes, etc..</p>
<div>
<div>
<pre><code><span>#### THIS WON'T WORK ####</span><span>
</span><span>PlotMe</span><span> </span><span>&lt;-</span><span> </span><span>function</span><span>(</span><span>dataframe</span><span>,</span><span>x</span><span>,</span><span>y</span><span>){</span><span>
</span><span>dataframe</span><span> </span><span>%>%</span><span>
</span><span>filter</span><span>(</span><span>!</span><span>is.na</span><span>(</span><span>x</span><span>),</span><span> </span><span>!</span><span>is.na</span><span>(</span><span>y</span><span>))</span><span> </span><span>%>%</span><span>
</span><span>group_by</span><span>(</span><span>x</span><span>,</span><span>y</span><span>)</span><span> </span><span>%>%</span><span>
</span><span>count</span><span>()</span><span> </span><span>%>%</span><span>
</span><span>ggplot</span><span>(</span><span>aes</span><span>(</span><span>fill</span><span>=</span><span>x</span><span>,</span><span> </span><span>y</span><span>=</span><span>n</span><span>,</span><span> </span><span>x</span><span>=</span><span>y</span><span>))</span><span> </span><span>+</span><span>
</span><span>geom_bar</span><span>(</span><span>position</span><span>=</span><span>&quot;dodge&quot;</span><span>,</span><span> </span><span>stat</span><span>=</span><span>&quot;identity&quot;</span><span>)</span><span> </span><span>-></span><span>p</span><span>
</span><span>plot</span><span>(</span><span>p</span><span>)</span><span>
</span><span>}</span><span>
</span><span>PlotMe</span><span>(</span><span>OfInterest</span><span>,</span><span>EDUCATION</span><span>,</span><span>NOTCOV</span><span>)</span><span>
</span><span>#### THIS WON'T WORK ####</span><span>
</span></code></pre>
</div>
</div>
<p>If you read all those references above (and your head doesn’t explode)<br>
you’ll learn how it can be done. Actually the references are very good<br>
and you will learn, I’m just here to give you a very practical example<br>
using a real world scenario.</p>
<div>
<div>
<pre><code><span>PlotMe</span><span> </span><span>&lt;-</span><span> </span><span>function</span><span>(</span><span>dataframe</span><span>,</span><span>x</span><span>,</span><span>y</span><span>){</span><span>
</span><span>aaa</span><span> </span><span>&lt;-</span><span> </span><span>enquo</span><span>(</span><span>x</span><span>)</span><span>
</span><span>bbb</span><span> </span><span>&lt;-</span><span> </span><span>enquo</span><span>(</span><span>y</span><span>)</span><span>
</span><span>dataframe</span><span> </span><span>%>%</span><span>
</span><span>filter</span><span>(</span><span>!</span><span>is.na</span><span>(</span><span>!!</span><span> </span><span>aaa</span><span>),</span><span> </span><span>!</span><span>is.na</span><span>(</span><span>!!</span><span> </span><span>bbb</span><span>))</span><span> </span><span>%>%</span><span>
</span><span>group_by</span><span>(</span><span>!!</span><span> </span><span>aaa</span><span>,</span><span>!!</span><span> </span><span>bbb</span><span>)</span><span> </span><span>%>%</span><span>
</span><span>count</span><span>()</span><span> </span><span>%>%</span><span>
</span><span>ggplot</span><span>(</span><span>aes_</span><span>(</span><span>fill</span><span>=</span><span>aaa</span><span>,</span><span> </span><span>y</span><span>=~</span><span>n</span><span>,</span><span> </span><span>x</span><span>=</span><span>bbb</span><span>))</span><span> </span><span>+</span><span>
</span><span>geom_bar</span><span>(</span><span>position</span><span>=</span><span>&quot;dodge&quot;</span><span>,</span><span> </span><span>stat</span><span>=</span><span>&quot;identity&quot;</span><span>)</span><span> </span><span>-></span><span>p</span><span>
</span><span>plot</span><span>(</span><span>p</span><span>)</span><span> </span><span># not strictly necessary</span><span>
</span><span>}</span><span>
</span><span>PlotMe</span><span>(</span><span>OfInterest</span><span>,</span><span>EDUCATION</span><span>,</span><span>NOTCOV</span><span>)</span><span>
</span></code></pre>
</div>
</div>
<p><img alt="" src="https://i1.wp.com/ibecav.github.io/images/therightway1-1.png?w=456" data-recalc-dims="1"></p>
<h2>“Banging” out an NSE solution (pun intended)</h2>
<p>If you compare the two functions you are immediately struck by a few<br>
extra lines of code that include <code>enquo</code>, a plethora of exclamation<br>
marks (a.k.a. “bang”) in the <code>dplyr</code> section and some underscores and a<br>
tilde “~” in the <code>ggplot</code> section. Let’s address them in order.</p>
<p>When we call the <code>PlotMe</code> function <code>PlotMe(OfInterest,EDUCATION,NOTCOV)</code><br>
we are passing it the name of our dataset <code>OfInterest</code> and two bare<br>
variables (<code>EDUCATION,NOTCOV</code>) <strong>N.B. it wouldn’t matter if they were<br>
quoted</strong> we’d still have to do something. The problem is that <code>R</code> can’t<br>
precisely understand what we want. It’s not 100% certain that<br>
<code>EDUCATION</code> &amp; <code>NOTCOV</code> are variables contained in <code>OfInterest</code> they<br>
could be a lot of different things. By using <code>enquo</code> initially to sort<br>
of wrap them up and then <code>!!</code> within our <code>dplyr</code> commands we can make it<br>
clear. Let’s create a new function that isolates just the <code>dplyr</code><br>
portions of our code and ensure we’re getting a sensical answer.</p>
<div>
<div>
<pre><code><span>JustDplyr</span><span> </span><span>&lt;-</span><span> </span><span>function</span><span>(</span><span>dataframe</span><span>,</span><span>x</span><span>,</span><span>y</span><span>){</span><span>
</span><span>aaa</span><span> </span><span>&lt;-</span><span> </span><span>enquo</span><span>(</span><span>x</span><span>)</span><span>
</span><span>bbb</span><span> </span><span>&lt;-</span><span> </span><span>enquo</span><span>(</span><span>y</span><span>)</span><span>
</span><span>dataframe</span><span> </span><span>%>%</span><span>
</span><span>filter</span><span>(</span><span>!</span><span>is.na</span><span>(</span><span>!!</span><span> </span><span>aaa</span><span>),</span><span> </span><span>!</span><span>is.na</span><span>(</span><span>!!</span><span> </span><span>bbb</span><span>))</span><span> </span><span>%>%</span><span>
</span><span>group_by</span><span>(</span><span>!!</span><span> </span><span>aaa</span><span>,</span><span>!!</span><span> </span><span>bbb</span><span>)</span><span> </span><span>%>%</span><span>
</span><span>count</span><span>()</span><span> </span><span>-></span><span> </span><span>JustAnExample</span><span>
</span><span>return</span><span>(</span><span>as.data.frame</span><span>(</span><span>JustAnExample</span><span>))</span><span>
</span><span>}</span><span>
</span><span>JustDplyr</span><span>(</span><span>OfInterest</span><span>,</span><span>EDUCATION</span><span>,</span><span>NOTCOV</span><span>)</span><span>
</span></code></pre>
</div>
</div>
<div>
<div>
<pre><code>##                          EDUCATION      NOTCOV     n
## 1      Bachelor's degree or higher     Covered 20802
## 2      Bachelor's degree or higher Not covered   895
## 3         High School Grad or less     Covered 43404
## 4         High School Grad or less Not covered  6846
## 5 Some college or Associate degree     Covered 20667
## 6 Some college or Associate degree Not covered  2313
</code></pre>
</div>
</div>
<p>Good. That’s what we want to see. Without the enquoting and the banging<br>
we’ll get consistent symptoms that it doesn’t know what <code>EDUCATION</code> &amp;<br>
<code>NOTCOV</code> are.</p>
<p><code>ggplot</code> like <code>dplyr</code> uses <code>NSE</code> by default to understand the data you<br>
are passing it in the <code>aes</code> section of the function (see<br>
?ggplot2::aes_). That makes our life much easier for interactive work<br>
but necessitates <code>aes_</code> in this case so we can weave it into our<br>
function. <code>aaa</code> and <code>bbb</code> are already enquoted and using <code>aes_</code> ensures<br>
that <code>ggplot</code> accounts for that. <code>~n</code> is the syntax for telling <code>aes_</code><br>
that it should find a variable called <code>n</code> inside the dataframe it is<br>
being passed from <code>dplyr</code> rather than looking for some other object<br>
named <code>n</code>.</p>
<div>
<div>
<pre><code><span>#### this is just a snippet and won't run on it's own</span><span>
</span><span>ggplot</span><span>(</span><span>aes_</span><span>(</span><span>fill</span><span>=</span><span>aaa</span><span>,</span><span> </span><span>y</span><span>=~</span><span>n</span><span>,</span><span> </span><span>x</span><span>=</span><span>bbb</span><span>))</span><span> </span><span>+</span><span>
</span><span>geom_bar</span><span>(</span><span>position</span><span>=</span><span>&quot;dodge&quot;</span><span>,</span><span> </span><span>stat</span><span>=</span><span>&quot;identity&quot;</span><span>)</span><span> </span><span>-></span><span>p</span><span>
</span></code></pre>
</div>
</div>
<p>A friendly reminder that as my tagline indicates I don’t consider myself<br>
a “programmer”. I love analyzing data and I love <code>R</code> but I approach<br>
programming slowly and cautiously. What I’m about to explain as my<br>
method will likely seem quaint and even antiquated to some but has the<br>
advantage of being very methodical and very practical. There are lots of<br>
places on the web to read about this stuff, I’m simply making the case I<br>
hope mine is slow and enough and methodical enough for a beginner.</p>
<p>We have a nice working function called <code>PlotMe</code>. We’ve proved up above<br>
that it works and having it means that if we change something inside the<br>
function (like add a title to our plot) it will apply itself every time.</p>
<p>We now face <a rel="nofollow" href="https://ibecav.github.io/Functionalize/" target="_blank">a similiar problem to the one we had the other<br>
day</a>. We want to take our<br>
really cool new function and apply it to lots of variables, not<br>
constantly specify the pair we want. Let’s use the same tactic we did<br>
then and make two lists of which variables we want. This time I am<br>
deliberately choosing to make both lists shorter. That’s only because<br>
we’re going to draw plots eventually and they take up a lot of room on<br>
the screen.</p>
<p>The other key thing to notice compared to my earlier post is the use of<br>
<code>as.name</code>. Since we wrote our function to accept <strong>“bare variable<br>
names”</strong> we have to make sure to put bare variables names into the<br>
list. Last time we used <code>OfInterest$NOTCOV</code> for example and <code>R</code> knew<br>
exactly what that was. If you try <code>list(NOTCOV, MEDBILL)</code> you will fail<br>
with an error message of <code>Error: object 'NOTCOV' not found</code>. If you try<br>
<code>depvars &lt;- list(&quot;NOTCOV&quot;, &quot;MEDBILL&quot;)</code> it won’t <strong>fail</strong> it will do<br>
worse and give you a plot that doesn’t make sense because it was<br>
expecting a bare variable name.</p>
<div>
<div>
<pre><code><span>PlotMe</span><span> </span><span>&lt;-</span><span> </span><span>function</span><span>(</span><span>dataframe</span><span>,</span><span>x</span><span>,</span><span>y</span><span>){</span><span>
</span><span>aaa</span><span> </span><span>&lt;-</span><span> </span><span>enquo</span><span>(</span><span>x</span><span>)</span><span>
</span><span>bbb</span><span> </span><span>&lt;-</span><span> </span><span>enquo</span><span>(</span><span>y</span><span>)</span><span>
</span><span>dataframe</span><span> </span><span>%>%</span><span>
</span><span>filter</span><span>(</span><span>!</span><span>is.na</span><span>(</span><span>!!</span><span> </span><span>aaa</span><span>),</span><span> </span><span>!</span><span>is.na</span><span>(</span><span>!!</span><span> </span><span>bbb</span><span>))</span><span> </span><span>%>%</span><span>
</span><span>group_by</span><span>(</span><span>!!</span><span> </span><span>aaa</span><span>,</span><span>!!</span><span> </span><span>bbb</span><span>)</span><span> </span><span>%>%</span><span>
</span><span>count</span><span>()</span><span> </span><span>%>%</span><span>
</span><span>ggplot</span><span>(</span><span>aes_</span><span>(</span><span>fill</span><span>=</span><span>aaa</span><span>,</span><span> </span><span>y</span><span>=~</span><span>n</span><span>,</span><span> </span><span>x</span><span>=</span><span>bbb</span><span>))</span><span> </span><span>+</span><span>
</span><span>geom_bar</span><span>(</span><span>position</span><span>=</span><span>&quot;dodge&quot;</span><span>,</span><span> </span><span>stat</span><span>=</span><span>&quot;identity&quot;</span><span>)</span><span> </span><span>-></span><span>p</span><span>
</span><span># plot(p) # not strictly necessary</span><span>
</span><span>}</span><span>
</span><span>depvars</span><span> </span><span>&lt;-</span><span> </span><span>list</span><span>(</span><span>as.name</span><span>(</span><span>&quot;NOTCOV&quot;</span><span>),</span><span> </span><span>as.name</span><span>(</span><span>&quot;MEDBILL&quot;</span><span>))</span><span>
</span><span>indvars</span><span> </span><span>&lt;-</span><span> </span><span>list</span><span>(</span><span>as.name</span><span>(</span><span>&quot;EARNINGS&quot;</span><span>),</span><span> </span><span>as.name</span><span>(</span><span>&quot;AGE&quot;</span><span>))</span><span>
</span><span>lapply</span><span> </span><span>(</span><span>indvars</span><span>,</span><span> </span><span>PlotMe</span><span>,</span><span> </span><span>dataframe</span><span>=</span><span>OfInterest</span><span>,</span><span> </span><span>y</span><span> </span><span>=</span><span>NOTCOV</span><span>)</span><span>
</span></code></pre>
</div>
</div>
<div>
<div>
<pre><code>## [[1]]
</code></pre>
</div>
</div>
<p><img alt="" src="https://i1.wp.com/ibecav.github.io/images/lists3-1.png?w=456" data-recalc-dims="1"></p>
<div>
<div>
<pre><code>## 
## [[2]]
</code></pre>
</div>
</div>
<p><img alt="" src="https://i0.wp.com/ibecav.github.io/images/lists3-2.png?w=456" data-recalc-dims="1"></p>
<div>
<div>
<pre><code><span>lapply</span><span> </span><span>(</span><span>depvars</span><span>,</span><span> </span><span>PlotMe</span><span>,</span><span> </span><span>dataframe</span><span>=</span><span>OfInterest</span><span>,</span><span> </span><span>x</span><span> </span><span>=</span><span>EDUCATION</span><span>)</span><span>
</span></code></pre>
</div>
</div>
<div>
<div>
<pre><code>## [[1]]
</code></pre>
</div>
</div>
<p><img alt="" src="https://i1.wp.com/ibecav.github.io/images/lists3-3.png?w=456" data-recalc-dims="1"></p>
<div>
<div>
<pre><code>## 
## [[2]]
</code></pre>
</div>
</div>
<p><img alt="" src="https://i1.wp.com/ibecav.github.io/images/lists3-4.png?w=456" data-recalc-dims="1"></p>
<div>
<div>
<pre><code><span>#lapply(depvars, function (x) lapply(indvars, function (y) PlotMe(dataframe=OfInterest,y=y,x=x)))</span><span>
</span></code></pre>
</div>
</div>
<p>Perfect! Just what we were looking for. We get back 4 plots. Progress!<br>
No surprise it works the other way around as well. We can hold the<br>
second part of the table command constant and just vary the independent<br>
variable via <code>indvars</code>!</p>
<p>What we need, of course, is both of those things. A <strong>“nested”</strong> set of<br>
calls to <code>lapply</code> to walk through both lists and give us all the tables<br>
not a subset. So I tried to do what I had earlier and nest one <code>lapply</code><br>
inside another. For the astute among you you will notice I have that<br>
line commented out. I tried to call <code>lapply</code> and tell it to run<br>
<code>lapply</code>! The second <code>lapply</code> should in turn call <code>Plotme</code> and all we<br>
have to do is to keep our x’s and y’s correct! <strong>Miserable failure!</strong></p>
<h3>Learning from failure</h3>
<p>I did quite a few variations with no success. Perhaps one day I’ll<br>
figure it out or one of you readers will point out the error of my ways.<br>
But undaunted I sat back and tried to figure a way to snatch success<br>
from this setback. The way I saw it I had at least two problems. One,<br>
the fact that the nested <code>lapply</code> wasn’t working but also that my<br>
process was just tedious. Building lists of variable names (quoted or<br>
bare) gets tedious. It’s a lot of typing and prone to errors. Perhaps<br>
I’d have more luck if I used the fact that each of the columns in a<br>
dataframe is also numbered… <code>OfInterest[,1]</code> corresponds to <code>AGE</code>. Maybe<br>
a more efficient way of approaching this problem was to take the<br>
dependent variable column numbers and cross them with the independent<br>
variable column numbers <code>OfInterest[,c(1,3:4,7)]</code> looked like a lot less<br>
typing than expressing <code>AGE SEX EDUCATION PNMED12M</code>. So the first two<br>
lines of code below put the right variables in <code>xwhich</code> and <code>ywhich</code> and<br>
are easy to verify!</p>
<div>
<div>
<pre><code><span>head</span><span>(</span><span>OfInterest</span><span>[,</span><span>c</span><span>(</span><span>6</span><span>:</span><span>9</span><span>)])</span><span>
</span></code></pre>
</div>
</div>
<div>
<div>
<pre><code>##   PDMED12M PNMED12M  NOTCOV MEDBILL
## 1       No       No Covered      No
## 2      Yes       No Covered     Yes
## 3       No       No Covered     Yes
## 4       No       No Covered     Yes
## 5       No       No Covered     Yes
## 6       No       No Covered      No
</code></pre>
</div>
</div>
<div>
<div>
<pre><code><span>xwhich</span><span> </span><span>&lt;-</span><span> </span><span>c</span><span>(</span><span>6</span><span>:</span><span>9</span><span>)</span><span>
</span><span>head</span><span>(</span><span>OfInterest</span><span>[,</span><span>c</span><span>(</span><span>1</span><span>,</span><span>4</span><span>,</span><span>5</span><span>)])</span><span>
</span></code></pre>
</div>
</div>
<div>
<div>
<pre><code>##            AGE                        EDUCATION         EARNINGS
## 1     19 to 60 Some college or Associate degree      $01-$34,999
## 2     19 to 60         High School Grad or less  $35,000-$74,999
## 3     19 to 60      Bachelor's degree or higher  $35,000-$74,999
## 4 Less than 18         High School Grad or less             </code></pre></div></div>