<p><div><div><div><div data-width="100" data-show-faces="false" data-send="true" data-layout="button_count" data-height="21" data-href="https://www.r-bloggers.com/organize-your-data-manipulation-in-terms-of-grouped-ordered-apply/"></div></div><div></div></div><div></div></div>
<div>
(This article was first published on <strong><a href="http://www.win-vector.com/blog/2016/12/organize-your-data-manipulation-in-terms-of-grouped-ordered-apply/"> R – Win-Vector Blog</a></strong>, and kindly contributed to <a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers)</a> </div>
<p>Consider the common following problem: compute for a data set (say the infamous <a target="_blank" rel="nofollow" href="https://stat.ethz.ch/R-manual/R-devel/library/datasets/html/iris.html"><code>iris</code></a> example data set) per-group ranks. Suppose we want the rank of <code>iris</code> <code>Sepal.Length</code>s on a per-<code>Species</code> basis. Frankly this is an “ugh” problem for many analysts: it involves all at the same time grouping, ordering, and window functions. It also is not likely ever the analyst’s end goal but a sub-step needed to transform data on the way to the prediction, modeling, analysis, or presentation they actually wish to get back to.</p>
<p><center><br>
<img title="Iris_germanica_(Purple_bearded_Iris),_Wakehurst_Place,_UK_-_Diliff.jpg" alt="Iris germanica Purple bearded Iris Wakehurst Place UK Diliff" src="https://i0.wp.com/www.win-vector.com/blog/wp-content/uploads/2016/12/Iris_germanica_Purple_bearded_Iris_Wakehurst_Place_UK_-_Diliff.jpg?resize=470%2C600" border="0" data-recalc-dims="1">Iris, by <a title="User:Diliff" target="_blank" rel="nofollow" href="http://commons.wikimedia.org/wiki/User:Diliff">Diliff</a> – <span lang="en">Own work</span>, <a title="Creative Commons Attribution-Share Alike 3.0" target="_blank" rel="nofollow" href="http://creativecommons.org/licenses/by-sa/3.0">CC BY-SA 3.0</a>, <a target="_blank" rel="nofollow" href="https://commons.wikimedia.org/w/index.php?curid=33037509">Link</a><br>
</center></p>
<p>In our <a target="_blank" rel="nofollow" href="http://www.win-vector.com/blog/2016/12/the-case-for-index-free-data-manipulation/">previous article in this series</a> we discussed the general ideas of “row-ID independent data manipulation” and “Split-Apply-Combine”. Here, continuing with our example, we will specialize to a data analysis pattern I call: “Grouped-Ordered-Apply”.<span></span></p>
<p>
<h2>The example</h2>
<p>Let’s start (as always) with our data. We are going to look at the <code>iris</code> data set in <a target="_blank" rel="nofollow" href="https://cran.r-project.org/"><code>R</code></a>. You can view the data in by typing the following in your <code>R</code> console:</p>
<p><code>
<pre>
data(iris)
View(iris)
</pre>
<p></p>
<p>The package <a target="_blank" rel="nofollow" href="https://cran.r-project.org/package=dplyr"><code>dplyr</code></a> makes the grouped calculation quite easy. We define our “window function” (function we want applied to sub-groups of data in a given order) and then use <code>dplyr</code> to apply the function to grouped and arranged data:</p>
<p><code>
<pre>
library('dplyr')

# define our windowed operation, in this case ranking
rank_in_group &lt;- . %>% mutate(constcol=1) %>%
          mutate(rank=cumsum(constcol)) %>% select(-constcol)

# calculate
res &lt;-
  iris %>% group_by(Species) %>% arrange(desc(Sepal.Length)) %>% 
  rank_in_group

# display first few results
res %>% filter(rank&lt;=2) %>% arrange(Species,rank)

 # Source: local data frame [6 x 6]
 # Groups: Species [3]
 # 
 #   Sepal.Length Sepal.Width Petal.Length Petal.Width    Species  rank
 #          </pre></code></code>