title: Re-ordering and appending an additional column to .SD output
body: <p>I would like to apply a scalar function (like <code>mean</code>) to a primary group, and rank the values within a secondary group. This is a sample code for what I am trying to do:</p>
  
  <pre><code>library(data.table)
  mytestdata &lt;- data.table(name=c("tom","john","tom","john","jim","jim","jack"),
                           len=c(10,15,12,23,3,12,3),
                           group=c("a","b","a","a","a","b","b"))
  mytestdata[, .SD[, .(mean(len), .N), by="name"][order(V1)], by = "group"]  # I need the .N to log
  </code></pre>
  
  <p>The output here is as I intend. However, when I try to rank the names within each group, I'm unable to get the desired output.</p>
  
  <pre><code>mytestdata[, .SD[, .(mean(len), .N), by="name"][order(V1), myrank := seq(1:.N)], by = "group"]
  </code></pre>
  
  <p>The above code assigns the rank correctly but re-orders the columns to the default ordering (ignoring <code>order(V1)</code>, which had worked in the previous line). I assume this has something to do with <code>:=</code> not displaying output. Is there a way to fix this?</p>
  
  <p>I tried something like</p>
  
  <pre><code>mytestdata[, .(.SD[, .(mean(len), .N), by="name"][order(V1)], seq(1:.N), by = "group"]
  </code></pre>
  
  <p>but it throws an error about bad usage of the <code>list()</code> method in <code>j</code>.</p>
  
  <p><strong>EDIT:</strong> My desired output is (ranking should be within group) <strong>(A)</strong></p>
  
  <pre><code>   group name V1 N myrank
  1:     a  jim  3 1    1
  2:     a  tom 11 2    2
  3:     a john 23 1    3
  4:     b jack  3 1    1
  5:     b  jim 12 1    2
  6:     b john 15 1    3
  </code></pre>
  
  <p><strong>EDIT:</strong> To clarify my point, my original code,</p>
  
  <pre><code>mytestdata[, .SD[, .(mean(len), .N), by="name"][order(V1)], by = "group"]
  </code></pre>
  
  <p>returns the datatable sorted in the way I'd like, i.e., <strong>(1)</strong></p>
  
  <pre><code>   group name V1 N
  1:     a  jim  3 1
  2:     a  tom 11 2
  3:     a john 23 1
  4:     b jack  3 1
  5:     b  jim 12 1
  6:     b john 15 1
  </code></pre>
  
  <p>Now, I'd like to keep this ordering and assign ranks to the names within each group. Since <code>i</code> is evaluated before <code>j</code> in a data.table, I can assign the rank in the same statement as <code>order()</code> above, i.e.,</p>
  
  <pre><code>mytestdata[, .SD[, .(mean(len), .N), by="name"][order(V1), myrank := 1:.N], by = "group"]
  </code></pre>
  
  <p>This assigns the rank correctly, i.e., <strong>(2)</strong></p>
  
  <pre><code>   group name V1 N myrank
  1:     a  tom 11 2      2
  2:     a john 23 1      3
  3:     a  jim  3 1      1
  4:     b john 15 1      3
  5:     b  jim 12 1      2
  6:     b jack  3 1      1
  </code></pre>
  
  <p>However, the ordering of rows is no longer the same as in <strong>(1)</strong> due to, my guess, the assignment operator suppressing output and storing the data table in the unordered format. Now, to get the output in the form of <strong>(A)</strong>, I have to re-order the rows by grouping again <strong>or</strong> assign the rank column in a chaining method, i.e.,</p>
  
  <pre><code>mytestdata[, .SD[, .(mean(len), .N), by="name"][order(V1), myrank := 1:.N], by = "group"][order(rank), .SD, by = "group"]
  </code></pre>
  
  <p><strong>(OR)</strong></p>
  
  <pre><code>mytestdata[, .SD[, .(mean(len), .N), by="name"][order(V1)], by = "group"][, myrank := 1:.N, by = "group"]
  </code></pre>
  
  <p>This gives the desired output <strong>(A)</strong>. While both these solve my problem, I'm curious whether there is a solution that does away with the additional chaining, since the ranks are assigned correctly in <strong>(2)</strong>, and the order is already correct in <strong>(1)</strong>.</p>