title: How to randomly filter rows to achieve desired proportions of a grouping variable
body: <p>I have data with a group variable, and I want to sample rows to end up with certain proportions in the group variable. This might require filtering rows, as the following example shows.</p>
  <p><strong>Simulating data</strong></p>
  <pre class="lang-r prettyprint-override"><code>set.seed(2021)
  
  my_df &lt;-
    data.frame(animal = sample(rep(c(&quot;dog&quot;, &quot;cat&quot;, &quot;rabbit&quot;), times = c(150, 4100, 220))),
             weight = sample(5:25, size = 4470, replace = TRUE))
  
  &gt; head(my_df)
  ##   animal weight
  ## 1    cat     11
  ## 2    cat     24
  ## 3    cat      9
  ## 4    cat     20
  ## 5    cat     11
  ## 6 rabbit      9
  </code></pre>
  <p>Here we have data about 4470 animals, which could be either cat, dog, or rabbit, and the weight of each individual animal.</p>
  <p>If we summarize the proportions of animals of each type we get:</p>
  <pre class="lang-r prettyprint-override"><code>library(dplyr)
  
  my_df %&gt;%
    group_by(animal) %&gt;%
    summarise(n = n()) %&gt;%
    mutate(freq = n / sum(n))
  
  ## # A tibble: 3 x 3
  ##   animal     n   freq
  ## * &lt;chr&gt;  &lt;int&gt;  &lt;dbl&gt;
  ## 1 cat     4100 0.917 
  ## 2 dog      150 0.0336
  ## 3 rabbit   220 0.0492
  </code></pre>
  <p>We thus learned that in <code>my_df</code>, 91.7% of the data are cats, 4.92% are rabbits, and 3.36% are dogs.</p>
  <hr />
  <p><strong>Desired Output: Sampling rows from the data to end up with other proportions over <code>animal</code> column</strong>
  <br>
  I realized that my data in <code>my_df</code> is not representative of the population I study, and therefore I want to sample rows to alter the proportions.</p>
  <p>I want to end up with data that is comprised of 70% cats, 15% dogs, and 15% rabbits. Obviously, I'll need to throw away many of the <code>cat</code> rows to reach such distribution.</p>
  <p>Is there a simple way to reach such random sampling, to meet a desired proportion over a grouping variable?</p>
  <hr />
  <p>EDIT</p>
  <hr />
  <p>To clarify, in <code>my_df</code> reaching the desired proportions between cat:dog:rabbit requires throwing away not only cats, but potentially dogs and rabbits too.</p>
  <hr />
  <p>EDIT 2</p>
  <hr />
  <p>In the comments, @Limey suggested <a href="https://stackoverflow.com/questions/66476142/sample-from-a-data-frame-using-group-specific-sample-sizes">this post</a>, which is indeed relevant. However, I've tried applying <a href="https://stackoverflow.com/a/66476655/6105259">this</a> solution from there but it didn't give the expected output.</p>
  <pre class="lang-r prettyprint-override"><code>library(purrr)
  
  group_slice_prop &lt;- c(cat = 0.7, dog = 0.15, rabbit = 0.15)
  
  output &lt;-
    my_df %&gt;% 
    split(.$animal) %&gt;% 
    imap_dfr(~ slice_sample(.x, prop = group_slice_prop[.y]))
  </code></pre>
  <p>We get that <code>output</code> is:</p>
  <pre class="lang-r prettyprint-override"><code>output %&gt;%
    group_by(animal) %&gt;%
    summarise(n = n()) %&gt;%
    mutate(freq = n / sum(n))
  
  ## # A tibble: 3 x 3
  ##   animal     n    freq
  ## * &lt;chr&gt;  &lt;int&gt;   &lt;dbl&gt;
  ## 1 cat     2870 0.981  
  ## 2 dog       22 0.00752
  ## 3 rabbit    33 0.0113 
  </code></pre>
  <p>But I was expecting to summarize <code>output</code> and get:</p>
  <pre class="lang-r prettyprint-override"><code># A tibble: 3 x 3
    animal     n    freq
  * &lt;chr&gt;  &lt;int&gt;   &lt;dbl&gt;
  1 cat       ?     0.70  
  2 dog       ?     0.15
  3 rabbit    ?     0.15 
  </code></pre>
  <hr />
  <p>EDIT 3</p>
  <hr />
  <p>Both @AnilGoyal and @Chris Ruehlemann proposed solutions that <em>do</em> work in this case, but are somewhat limited to the toy data I provided. We could have thought about other scenarios with different, less intuitive proportions, or otherwise more levels in the group variable that require different math to figure out the <code>n</code> per group. I want to avoid that. I wish to specify the desired <em>blend of proportions</em> in the group variable, and let the code decide how many rows to throw away from each group category to reach that blend.</p>