<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/collapsing-categories-or-values/"></div></div><div></div></div><div></div></div>
<div>
(This article was first published on <strong><a href="http://derekogle.com/fishR/2018-03-30-Collapsing_Values"> fishR Blog</a></strong>, and kindly contributed to <a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers)</a> </div>
<hr>
<h2>Introduction</h2>
<p>I have received a few queries recently that can be categorized as “How do I collapse a list of categories or values into a shorter list of category or values?” For example, one user wanted to collapse species of fish into their respective families. Another user wanted to collapse years into decades. Data munging such as this is common in fisheries. Thus, I provide a quick demonstration here of one way to accomplish these tasks using tools from the <a rel="nofollow" href="https://www.tidyverse.org/" target="_blank">tidyverse</a>.</p>
<p>This post requires the <code>dplyr</code>, <code>magrittr</code>, and <code>plyr</code> packages. Note, however, that <code>plyr</code> is not loaded below because I am only going to use one specific function from <code>plyr</code> (i.e., <code>mapvalues()</code>) and I have found that <code>plyr</code> and <code>dplyr</code> don’t always “play well” together.[^1]</p>
<figure>
<pre><code data-lang="r"><span>library</span><span>(</span><span>dplyr</span><span>)</span><span> </span><span># for mutate(), %>%</span><span>
</span><span>library</span><span>(</span><span>magrittr</span><span>)</span><span> </span><span># for %&lt;>%</span></code></pre>
</figure>
<p>Because I am creating random example data below, I set the random number seed to make the results reproducible.</p>
<figure>
<pre><code data-lang="r"><span>set.seed</span><span>(</span><span>678394</span><span>)</span></code></pre>
</figure>
<h2>Create A Sample of Data</h2>
<p>The following creates a very simple sample of 250 individuals on which the species (as a short abbreviation) and year of capture were recorded.</p>
<figure>
<pre><code data-lang="r"><span>n</span><span> </span><span>&lt;-</span><span> </span><span>250</span><span>
</span><span>dat</span><span> </span><span>&lt;-</span><span> </span><span>data.frame</span><span>(</span><span>species</span><span>=</span><span>sample</span><span>(</span><span>c</span><span>(</span><span>&quot;BLG&quot;</span><span>,</span><span>&quot;LMB&quot;</span><span>,</span><span>&quot;PKS&quot;</span><span>,</span><span>&quot;WAE&quot;</span><span>,</span><span>&quot;YEP&quot;</span><span>,</span><span>&quot;CRP&quot;</span><span>),</span><span>
</span><span>n</span><span>,</span><span>replace</span><span>=</span><span>TRUE</span><span>),</span><span>
</span><span>year</span><span>=</span><span>sample</span><span>(</span><span>1980</span><span>:</span><span>2017</span><span>,</span><span>n</span><span>,</span><span>replace</span><span>=</span><span>TRUE</span><span>))</span><span>
</span><span>head</span><span>(</span><span>dat</span><span>)</span></code></pre>
</figure>
<figure>
<pre><code data-lang="text">##   species year
## 1     PKS 1981
## 2     CRP 1998
## 3     YEP 1983
## 4     YEP 2003
## 5     LMB 2009
## 6     CRP 1994</code></pre>
</figure>
<h2>Example 1 – Recode and Collapse Categories</h2>
<p>The <code>mutate()</code> function may be used to add a new variable to a data.frame. The <code>mapvalues()</code> function (from <code>plyr</code>) may be use to efficiently recode character (or factor) values <em>in a vector</em>. Because <code>mapvalues()</code> operates on a vector, it must be used within <code>mutate()</code> to add a new variable with the recoded values to a data.frame. When used within <code>mutate()</code>, the first argument to <code>mapvalues()</code> is the vector that contains the original data to be recoded. A vector of categories for these original data are then given in <code>from=</code> and a vector of <strong>new</strong> categories for these data are given in <code>to=</code>.</p>
<p>I find it most simple to first create vectors of categories for <code>from=</code> and <code>to=</code> and then use them in <code>mapvalues()</code>. For example, the use of <code>levels()</code> below extracts (and saves into <code>short</code>) the vector of species abbreviations found in the <code>species</code> variable of the example data.</p>
<figure>
<pre><code data-lang="r"><span>(</span><span> </span><span>short</span><span> </span><span>&lt;-</span><span> </span><span>levels</span><span>(</span><span>dat</span><span>$</span><span>species</span><span>)</span><span> </span><span>)</span></code></pre>
</figure>
<figure>
<pre><code data-lang="text">## [1] &quot;BLG&quot; &quot;CRP&quot; &quot;LMB&quot; &quot;PKS&quot; &quot;WAE&quot; &quot;YEP&quot;</code></pre>
</figure>
<p>“New categories” that correspond to each of the original categories may then be entered into a vector. For example, the <code>long</code> vector below contains the long-form names for each species (in the same order as the abbreviations in <code>short</code>) and <code>family</code> contains the corresponding family names.</p>
<figure>
<pre><code data-lang="r"><span>long</span><span> </span><span>&lt;-</span><span> </span><span>c</span><span>(</span><span>&quot;Bluegill&quot;</span><span>,</span><span>&quot;Carp&quot;</span><span>,</span><span>&quot;Largemouth Bass&quot;</span><span>,</span><span>
</span><span>&quot;Pumpkinseed&quot;</span><span>,</span><span>&quot;Walleye&quot;</span><span>,</span><span>&quot;Yellow Perch&quot;</span><span>)</span><span>
</span><span>fam</span><span> </span><span>&lt;-</span><span> </span><span>c</span><span>(</span><span>&quot;Centrarchidae&quot;</span><span>,</span><span>&quot;Cyprinidae&quot;</span><span>,</span><span>&quot;Centrarchidae&quot;</span><span>,</span><span>
</span><span>&quot;Centrarchidae&quot;</span><span>,</span><span>&quot;Percidae&quot;</span><span>,</span><span>&quot;Percidae&quot;</span><span>)</span></code></pre>
</figure>
<p>“Column bind” these vectors together to make sure that the categories are correctly matched across the vectors.</p>
<figure>
<pre><code data-lang="r"><span>cbind</span><span>(</span><span>short</span><span>,</span><span>long</span><span>,</span><span>fam</span><span>)</span></code></pre>
</figure>
<figure>
<pre><code data-lang="text">##      short long              fam            
## [1,] &quot;BLG&quot; &quot;Bluegill&quot;        &quot;Centrarchidae&quot;
## [2,] &quot;CRP&quot; &quot;Carp&quot;            &quot;Cyprinidae&quot;   
## [3,] &quot;LMB&quot; &quot;Largemouth Bass&quot; &quot;Centrarchidae&quot;
## [4,] &quot;PKS&quot; &quot;Pumpkinseed&quot;     &quot;Centrarchidae&quot;
## [5,] &quot;WAE&quot; &quot;Walleye&quot;         &quot;Percidae&quot;     
## [6,] &quot;YEP&quot; &quot;Yellow Perch&quot;    &quot;Percidae&quot;</code></pre>
</figure>
<p>The combined use of <code>mutate()</code> and <code>mapvalues()</code> below demonstrates how these vectors may be used to change the original abbreviated names to long-form names or family names. In addition, the last use of <code>mapvalues()</code> shows how to change the long-form names to family names. This last example is, of course, repetitive, but it is used here to demonstrate how <code>mutate()</code> allows a variable that was “just created” to be immediately used.</p>
<figure>
<pre><code data-lang="r"><span>dat</span><span> </span><span>%&lt;>%</span><span>
</span><span>mutate</span><span>(</span><span>speciesL</span><span>=</span><span>plyr</span><span>::</span><span>mapvalues</span><span>(</span><span>species</span><span>,</span><span>from</span><span>=</span><span>short</span><span>,</span><span>to</span><span>=</span><span>long</span><span>),</span><span>
</span><span>family</span><span>=</span><span>plyr</span><span>::</span><span>mapvalues</span><span>(</span><span>species</span><span>,</span><span>from</span><span>=</span><span>short</span><span>,</span><span>to</span><span>=</span><span>fam</span><span>),</span><span>
</span><span>family2</span><span>=</span><span>plyr</span><span>::</span><span>mapvalues</span><span>(</span><span>speciesL</span><span>,</span><span>from</span><span>=</span><span>long</span><span>,</span><span>to</span><span>=</span><span>fam</span><span>))</span><span>
</span><span>head</span><span>(</span><span>dat</span><span>)</span></code></pre>
</figure>
<figure>
<pre><code data-lang="text">##   species year        speciesL        family       family2
## 1     PKS 1981     Pumpkinseed Centrarchidae Centrarchidae
## 2     CRP 1998            Carp    Cyprinidae    Cyprinidae
## 3     YEP 1983    Yellow Perch      Percidae      Percidae
## 4     YEP 2003    Yellow Perch      Percidae      Percidae
## 5     LMB 2009 Largemouth Bass Centrarchidae Centrarchidae
## 6     CRP 1994            Carp    Cyprinidae    Cyprinidae</code></pre>
</figure>
<p>Note in the code above that the use of <code>plyr::</code> in front of <code>mapvalues()</code> allows the user to use the <code>mapvalues()</code> function from <code>plyr</code> without loading the entire <code>plyr</code> package.[^2] As noted previously, this idiom is used here to avoid potential conflicts between <code>plyr</code> and <code>dplyr</code>.</p>
<p>Note that this use of <code>mapvalues()</code> and <code>mutate()</code> is described in Section 2.2.7 of my book <a rel="nofollow" href="http://derekogle.com/IFAR/" target="_blank">Introductory Fisheries Analyses with R</a>.</p>
<h2>Example 2 – Collapse Values into Categories</h2>
<p>The <code>case_when()</code> function (from <code>dplyr</code>) may be used to efficiently collapse discrete values into categories.[^3] This function also operates on vectors and, thus, must be used with <code>mutate()</code> to add a variable to a data.frame. The arguments to <code>case_when()</code> are a series of two-sided formulae where the left-side is a conditioning statement based on the original data and the right-side is the value that should appear in the new variable when that condition is <code>TRUE</code>. For example, the first line in <code>case_when()</code> below asks “if the year variable is in the values from 1980 to 1989 then the new category should be ‘1980s’.”[^4] For example, the code below creates a new variable called <code>decade</code> that identifies the decade that corresponds to the year-of-capture variable.</p>
<figure>
<pre><code data-lang="r"><span>dat</span><span> </span><span>%&lt;>%</span><span>
</span><span>mutate</span><span>(</span><span>decade</span><span>=</span><span>case_when</span><span>(</span><span>
</span><span>year</span><span> </span><span>%in%</span><span> </span><span>1980</span><span>:</span><span>1989</span><span> </span><span>~</span><span> </span><span>&quot;1980s&quot;</span><span>,</span><span>
</span><span>year</span><span> </span><span>%in%</span><span> </span><span>1990</span><span>:</span><span>1999</span><span> </span><span>~</span><span> </span><span>&quot;1990s&quot;</span><span>,</span><span>
</span><span>year</span><span> </span><span>%in%</span><span> </span><span>2000</span><span>:</span><span>2009</span><span> </span><span>~</span><span> </span><span>&quot;2000s&quot;</span><span>,</span><span>
</span><span>year</span><span> </span><span>%in%</span><span> </span><span>2010</span><span>:</span><span>2019</span><span> </span><span>~</span><span> </span><span>&quot;2010s&quot;</span><span>
</span><span>))</span><span>
</span><span>head</span><span>(</span><span>dat</span><span>)</span></code></pre>
</figure>
<figure>
<pre><code data-lang="text">##   species year        speciesL        family       family2 decade
## 1     PKS 1981     Pumpkinseed Centrarchidae Centrarchidae  1980s
## 2     CRP 1998            Carp    Cyprinidae    Cyprinidae  1990s
## 3     YEP 1983    Yellow Perch      Percidae      Percidae  1980s
## 4     YEP 2003    Yellow Perch      Percidae      Percidae  2000s
## 5     LMB 2009 Largemouth Bass Centrarchidae Centrarchidae  2000s
## 6     CRP 1994            Carp    Cyprinidae    Cyprinidae  1990s</code></pre>
</figure>
<p>The lines in <code>case_when()</code> operate sequentially (like a series of “if” statements) such that the above operation can be more succinctly coded as below. Also note in this example the resulting variable is numeric rather than categorical (simply as an example).</p>
<figure>
<pre><code data-lang="r"><span>dat</span><span> </span><span>%&lt;>%</span><span>
</span><span>mutate</span><span>(</span><span>decade2</span><span>=</span><span>case_when</span><span>(</span><span>
</span><span>year</span><span> </span><span>&lt;=</span><span> </span><span>1989</span><span> </span><span>~</span><span> </span><span>1980</span><span>,</span><span>
</span><span>year</span><span> </span><span>&lt;=</span><span> </span><span>1999</span><span> </span><span>~</span><span> </span><span>1990</span><span>,</span><span>
</span><span>year</span><span> </span><span>&lt;=</span><span> </span><span>2009</span><span> </span><span>~</span><span> </span><span>2000</span><span>,</span><span>
</span><span>year</span><span> </span><span>&lt;=</span><span> </span><span>2019</span><span> </span><span>~</span><span> </span><span>2010</span><span>,</span><span>
</span><span>))</span><span>
</span><span>head</span><span>(</span><span>dat</span><span>)</span></code></pre>
</figure>
<figure>
<pre><code data-lang="text">##   species year        speciesL        family       family2 decade decade2
## 1     PKS 1981     Pumpkinseed Centrarchidae Centrarchidae  1980s    1980
## 2     CRP 1998            Carp    Cyprinidae    Cyprinidae  1990s    1990
## 3     YEP 1983    Yellow Perch      Percidae      Percidae  1980s    1980
## 4     YEP 2003    Yellow Perch      Percidae      Percidae  2000s    2000
## 5     LMB 2009 Largemouth Bass Centrarchidae Centrarchidae  2000s    2000
## 6     CRP 1994            Carp    Cyprinidae    Cyprinidae  1990s    1990</code></pre>
</figure>
<figure>
<pre><code data-lang="r"><span>str</span><span>(</span><span>dat</span><span>)</span></code></pre>
</figure>
<figure>
<pre><code data-lang="text">## 'data.frame':	250 obs. of  7 variables:
##  $ species : Factor w/ 6 levels &quot;BLG&quot;,&quot;CRP&quot;,&quot;LMB&quot;,..: 4 2 6 6 3 2 4 4 1 6 ...
##  $ year    : int  1981 1998 1983 2003 2009 1994 2001 2006 1994 1991 ...
##  $ speciesL: Factor w/ 6 levels &quot;Bluegill&quot;,&quot;Carp&quot;,..: 4 2 6 6 3 2 4 4 1 6 ...
##  $ family  : Factor w/ 3 levels &quot;Centrarchidae&quot;,..: 1 2 3 3 1 2 1 1 1 3 ...
##  $ family2 : Factor w/ 3 levels &quot;Centrarchidae&quot;,..: 1 2 3 3 1 2 1 1 1 3 ...
##  $ decade  : chr  &quot;1980s&quot; &quot;1990s&quot; &quot;1980s&quot; &quot;2000s&quot; ...
##  $ decade2 : num  1980 1990 1980 2000 2000 1990 2000 2000 1990 1990 ...</code></pre>
</figure>
<hr>
<h2>Footnotes</h2>
<p>[^1] This may not be a concern with recent versions of <code>plyr</code> and <code>dplyr</code>. However, I have been bitten by enough problems when I have both of these packages loaded that I prefer to use the cautionary approach that I take in this post.</p>
<p>[^2] The <code>FSA</code> package imports <code>mapvalues</code> from <code>plyr</code> and then exports it. Thus, if you have loaded the <code>FSA</code> package then you will not need to use the <code>plyr::</code> idiom.</p>
<p>[^3] You may also want to consider <code>cut()</code> for this purpose or, for collapsing continuous data into categories, <code>lencat()</code> from the <code>FSA</code> package.</p>
<p>[^4] The colon operator creates a sequence of all integers between the two numbers separated by the colon. The <code>%in%</code> is used on conditional statements to determine if a value is contained with a vector, returning <code>TRUE</code> if it is and <code>FALSE</code> if it is not.</p>
	<p>
<div>
<div>To <strong>leave a comment</strong> for the author, please follow the link and comment on their blog: <strong><a href="http://derekogle.com/fishR/2018-03-30-Collapsing_Values"> fishR Blog</a></strong>.</div>
<hr>
<a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers.com</a> offers <strong><a rel="nofollow" href="https://feedburner.google.com/fb/a/mailverify?uri=RBloggers">daily e-mail updates</a></strong> about <a rel="nofollow" href="https://www.r-project.org/" title="The R Project for Statistical Computing">R</a> news and <a rel="nofollow" href="https://www.r-bloggers.com/search/tutorial" title="R tutorials">tutorials</a> on topics such as: <a rel="nofollow" href="https://www.r-bloggers.com/search/data%20science" title="Data science">Data science</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/Big%20Data" title="Big Data">Big Data, <a rel="nofollow" href="https://www.r-users.com/" title="R jobs">R jobs</a>, visualization (<a rel="nofollow" href="https://www.r-bloggers.com/search/ggplot2" title="ggplot and ggplot2 tutorials">ggplot2</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/boxplot" title="Boxplots using lattice and ggplot2 tutorials">Boxplots</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/map" title="Maps and gis">maps</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/animation" title="Animation in R">animation</a>), programming (<a rel="nofollow" href="https://www.r-bloggers.com/search/RStudio" title="RStudio IDE for R">RStudio</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/sweave" title="Sweave and literate programming">Sweave</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/LaTeX" title="LaTeX in R">LaTeX</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/SQL" title="SQL and databases">SQL</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/eclipse" title="Eclipse IDE for R">Eclipse</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/git" title="git and github, Version Control System">git</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/hadoop" title="Large data in R using Hadoop">hadoop</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/Web+Scraping" title="Web Scraping of google, facebook, yahoo, twitter and more using R">Web Scraping</a>) statistics (<a rel="nofollow" href="https://www.r-bloggers.com/search/regression" title="Regressions and ANOVA analysis tutorials">regression</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/PCA" title="principal component analysis tutorial">PCA</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/time+series" title="Time series">time series</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/trading" title="finance trading">trading</a>) and more...
<img width="1" alt="" src="http://feeds.feedburner.com/~r/RBloggers/~4/cYHWmjKpPUA" height="1"></a></div>