mikebader.net - Entries for the tag reproducible-researchhttps://mikebader.net/blog/tags/reproducible-research/The last entries tagged with reproducible-researchen-usZinniaSat, 03 Nov 2018 12:43:28 +0000Multiple Models with Same Independent Variables in R
https://mikebader.net/blog/entries/2018/11/02/multiple-models-same-independent-variables-r/<p><strong>tl;dr</strong>: paste outcome and dependent variables into R's <code>as.formula()</code> function to avoid typing the same models out repetitively.</p>
<p>The "don't repeat yourself" principle in programming tries to eliminate errors by eliminating repetitious code. When code repeats changing the code in one place requires making the same change everywhere the code repeats. Relying on memory to find all of the places where code should be replicated increases the chances that you introduce bugs by forgetting to change at least one place where the code repeats. </p>
<p>This principle applies to statistical coding. I am working on a paper that uses three sets of variables from the <a href="/projects/dc-area-survey/">2016 DCAS</a>: race, other demographic variables, socioeconomic variables, and variables measuring neighborhood experiences of respondents. I want to run three models for each outcome in the paper. </p>
<ol>
<li>
<p>A model with just race</p>
</li>
<li>
<p>A model with race, demographic, and socioeconomic variables</p>
</li>
<li>
<p>A model with race, demographic, socioeconomic, and neighborhood experience variables</p>
</li>
</ol>
<p>I will be using these same covariates in a series of four regression models. I could copy-and-paste the string of variable names in the formula each time. But that would violate the DRY principle. That wouldn't be a problem if I made the perfect set of models, triple checked that all of the models corresponded with one another, that I will never need to change anything. </p>
<p>What, however, happens when a reviewer points out a variable that should be in the models? If I was fortunate that the lack of the variable didn't sink the paper in the editor's eyes, I will need to add that variable into each model. I will return to my code after three months (or more) and try to remember to include the new variable in every model. That's no good and prone to error.</p>
<p>I will instead define the covariates in each of the three models early in the code. For my example case of three sets of variables, I would define the <em>independent variables</em> (not the outcome) in three character objects, <code>m1</code>, <code>m2</code>, and <code>m3</code>:</p>
<div class="codehilite"><pre><span></span>m1 <span class="o"><-</span> <span class="s">'dem.race'</span>
m2 <span class="o"><-</span> <span class="kp">paste0</span><span class="p">(</span>m1<span class="p">,</span> <span class="s">'+ age + forborn + man + kids + married + '</span><span class="p">,</span>
<span class="s">'educ1 + educ2 + educ3 + educ5 + inc1 + inc3 + inc4'</span><span class="p">)</span>
m3 <span class="o"><-</span> <span class="kp">paste0</span><span class="p">(</span>m2<span class="p">,</span> <span class="s">'+ nhdyrs + nhdsize1 + nhdsize3'</span><span class="p">)</span>
</pre></div>
<p>The three sets of variables correspond to the variables in the list of models above. Notice that I even used the DRY principle as I constructed the objects. Rather than repeat <code>dem.race</code> in <code>m2</code>, I pasted the value of <code>m1</code>--which equals <code>dem.race</code>--to the front of <code>m2</code>. I repeated the same thing for the third model by pasting the contents of <code>m2</code> into the front of <code>m3</code> (this works because the variables in my models are nested within one another). </p>
<p>To use these objects in the models of outcomes, I will need to include them in a <em>formula</em>. R provides a helper function, <code>as.formula()</code> to tell R that the string I enter should be interpreted as a formula in a model function. Notice that I did not define the dependent variable in the objects above. That's because I want to substitute in the dependent variable for each set of analyses. In the first set of models, my dependent variable is called <code>satisfied</code>. I would estimate my models using the following 116 characters of code (it could fit in a tweet!):</p>
<div class="codehilite"><pre><span></span>m1_sat <span class="o"><-</span> lm<span class="p">(</span><span class="kp">paste</span><span class="p">(</span><span class="s">'satisfied ~'</span><span class="p">,</span> m1<span class="p">),</span> data<span class="o">=</span>dcas<span class="p">)</span>
m2_sat <span class="o"><-</span> lm<span class="p">(</span><span class="kp">paste</span><span class="p">(</span><span class="s">'satisfied ~'</span><span class="p">,</span> m2<span class="p">),</span> data<span class="o">=</span>dcas<span class="p">)</span>
m3_sat <span class="o"><-</span> lm<span class="p">(</span><span class="kp">paste</span><span class="p">(</span><span class="s">'satisfied ~'</span><span class="p">,</span> m3<span class="p">),</span> data<span class="o">=</span>dcas<span class="p">)</span>
</pre></div>
<p>I pasted the dependent variable and tilde (<code>~</code>) to the front of the string containing the independent variables. I included all of that in the <code>as.formula()</code> function, and my model ran. </p>
<p>Doing this once isn't that exciting or probably even worth the effort. But I have a second outcome that I want to model using the same covariates. Normally, I would have to re-type all of those covariates into a formula. With our new trick, I can just paste the new dependent variable into the formula and estimate the same models with a new outcome (and still only 116 characters!):</p>
<div class="codehilite"><pre><span></span>m1_imp <span class="o"><-</span> lm<span class="p">(</span><span class="kp">paste</span><span class="p">(</span><span class="s">'improved ~'</span><span class="p">,</span> m1<span class="p">),</span> data<span class="o">=</span>dcas<span class="p">)</span>
m2_imp <span class="o"><-</span> lm<span class="p">(</span><span class="kp">paste</span><span class="p">(</span><span class="s">'improved ~'</span><span class="p">,</span> m2<span class="p">),</span> data<span class="o">=</span>dcas<span class="p">)</span>
m3_imp <span class="o"><-</span> lm<span class="p">(</span><span class="kp">paste</span><span class="p">(</span><span class="s">'improved ~'</span><span class="p">,</span> m3<span class="p">),</span> data<span class="o">=</span>dcas<span class="p">)</span>
</pre></div>
<p>Now I should have output for two sets of three models with the same covariates to analyze in my paper! I hope this helps. Speaking of Twitter, feel free to contact me there if you have questions (<a href="https://twitter.com/mike_bader">@mike_bader</a>).</p>
michaeldmbader@gmail.com (mikebader)Fri, 02 Nov 2018 21:24:02 +0000https://mikebader.net/blog/entries/2018/11/02/multiple-models-same-independent-variables-r/Methods