Thanks Harish! This works great.<br><br><div class="gmail_quote">On Tue, Jul 13, 2010 at 11:14 PM, Harish <span dir="ltr">&lt;<a href="mailto:harishv_99@yahoo.com">harishv_99@yahoo.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">
<div class="im">Small update.  The prior function did not handle when &quot;by&quot; was missing.  Also, I thought of a &quot;better&quot; way to remove duplicate columns...<br>
<br>
=================<br>
<br>
gen2 &lt;- function(data,by,...) {<br>
   if ( ! missing( by ) ) {<br>
</div><div class="im">      DT &lt;- eval( bquote( data[,transform(.SD,...),by=.(substitute(by)) ] ) )<br>
<br>
</div><div class="im">      # Remove duplicate columns<br>
      strCols &lt;- names( DT )<br>
      strDup &lt;- strCols[ duplicated( strCols ) ]<br>
      for ( str in strDup )<br>
         DT[[ str ]] &lt;- NULL<br>
   }<br>
   else {<br>
      DT &lt;- as.data.table( transform( data, ... ) )<br>
   }<br>
<br>
</div><div class="im">   return( DT )<br>
}<br>
<br>
<br>
gen2(x, by=x2, xSum = sum(x1))<br>
gen2(x, by=list(x2,x3), xSum = sum(x1))<br>
</div><div class="im">gen2(x, xSum=sum(x1))<br>
<br>
=================<br>
<br>
Please let me know if you find bugs in it or find a better way to do this.<br>
<br>
<br>
Regards,<br>
Harish<br>
<br>
<br>
--- On Tue, 7/13/10, Harish &lt;<a href="mailto:harishv_99@yahoo.com">harishv_99@yahoo.com</a>&gt; wrote:<br>
<br>
&gt; From: Harish &lt;<a href="mailto:harishv_99@yahoo.com">harishv_99@yahoo.com</a>&gt;<br>
&gt; Subject: Re: [datatable-help] data.table in functions<br>
&gt; To: <a href="mailto:datatable-help@lists.r-forge.r-project.org">datatable-help@lists.r-forge.r-project.org</a>, &quot;Sasha Goodman&quot; &lt;<a href="mailto:sashag@stanford.edu">sashag@stanford.edu</a>&gt;<br>
&gt; Date: Tuesday, July 13, 2010, 10:49 PM<br>
</div><div><div></div><div class="h5">&gt; Sasha,<br>
&gt;<br>
&gt; You should find code that works for you below along with a<br>
&gt; workaround to get rid of the &quot;.1&quot; columns.<br>
&gt;<br>
&gt; You were having an issue because you are treating the<br>
&gt; formula as text.  When you pass in a list, things<br>
&gt; aren&#39;t quite working out.  I didn&#39;t bother trying to<br>
&gt; figure out how it is actually interpreting it.<br>
&gt;<br>
&gt; I also put in a workaround for the duplicate columns you<br>
&gt; were getting.  You are right in that there was a flag<br>
&gt; to avoid that before (based on a discussion I read in the<br>
&gt; group).  Matthew is thinking about how to resolve<br>
&gt; this.<br>
&gt;<br>
&gt; Most of the lines in the function are for the workaround of<br>
&gt; getting rid of duplicate columns.  Maybe there is an<br>
&gt; easier way.<br>
&gt;<br>
&gt; The line...<br>
&gt;    DT &lt;- eval( bquote(<br>
&gt; data[,transform(.SD,...),by=.(substitute(by)) ] ) )<br>
&gt; is the main line of the function.<br>
&gt;<br>
&gt;<br>
&gt; gen2 &lt;- function(data,by,...) {<br>
&gt;    sby &lt;- substitute( by )<br>
&gt;    if ( length( sby ) &gt; 1 ) {<br>
&gt;       if ( sby[[1]] == &quot;list&quot; )<br>
&gt;          lst &lt;- as.list(<br>
&gt; sby )[ -1 ]<br>
&gt;    }<br>
&gt;    else<br>
&gt;       lst &lt;- list( deparse(sby) )<br>
&gt;<br>
&gt;    DT &lt;- eval( bquote(<br>
&gt; data[,transform(.SD,...),by=.(substitute(by)) ] ) )<br>
&gt;    lapply( lst, function(.i) DT[[.i]]<br>
&gt; &lt;&lt;- NULL )<br>
&gt;<br>
&gt;    return( DT )<br>
&gt; }<br>
&gt; gen2(x, by=x2, xSum = sum(x1))<br>
&gt; gen2(x, by=list(x2,x3), xSum = sum(x1))<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt; Harish<br>
&gt;<br>
&gt;<br>
&gt; --- On Mon, 7/12/10, Sasha Goodman &lt;<a href="mailto:sashag@stanford.edu">sashag@stanford.edu</a>&gt;<br>
&gt; wrote:<br>
&gt;<br>
&gt; &gt; From: Sasha Goodman &lt;<a href="mailto:sashag@stanford.edu">sashag@stanford.edu</a>&gt;<br>
&gt; &gt; Subject: [datatable-help] data.table in functions<br>
&gt; &gt; To: <a href="mailto:datatable-help@lists.r-forge.r-project.org">datatable-help@lists.r-forge.r-project.org</a><br>
&gt; &gt; Date: Monday, July 12, 2010, 4:22 PM<br>
&gt; &gt; Thanks for the emails, Matthew. I think our<br>
&gt; &gt; talk should be moved to the data.table discussion<br>
&gt; list.<br>
&gt; &gt;<br>
&gt; &gt; So, of all the data manipulation functions I&#39;ve used,<br>
&gt; &gt; the &#39;gen&#39; function (which is similar to Stata&#39;s<br>
&gt; &gt; egen function) has been the most useful. I would be<br>
&gt; very<br>
&gt; &gt; happy if it were adapted to data.tables.<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt; Here is the version that works with plyr.<br>
&gt; &gt;<br>
&gt; &gt; &gt;<br>
&gt; &gt; gen &lt;- function(data,  ... ,by=NA)<br>
&gt; &gt; {<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt;  if(!<a href="http://is.na" target="_blank">is.na</a>(by)) {<br>
&gt; &gt; require(plyr)<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt;   out =<br>
&gt; &gt; ddply(data,by, transform, ... )<br>
&gt; &gt; } else<br>
&gt; &gt; {<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt; out =<br>
&gt; &gt; transform(data,...)<br>
&gt; &gt; }<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt;   return(out)<br>
&gt; &gt; }<br>
&gt; &gt;<br>
&gt; &gt; &gt;<br>
&gt; &gt; y = data.frame(x1 = 1, x2 = rep(c(1,2), each=2),<br>
&gt; &gt; x3= rep(c(1,2),4))<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt; &gt; gen(y, xSum=<br>
&gt; &gt; sum(x1), by=c(&#39;x2&#39;))<br>
&gt; &gt;<br>
&gt; &gt;  <br>
&gt; &gt;   x1 x2 x3 xSum<br>
&gt; &gt; 1  1  1  1    4<br>
&gt; &gt; 2  1  1  2    4<br>
&gt; &gt; 3  1  1  1    4<br>
&gt; &gt; 4  1  1  2    4<br>
&gt; &gt; 5  1  2  1    4<br>
&gt; &gt;<br>
&gt; &gt; 6  1  2  2    4<br>
&gt; &gt; 7  1  2  1    4<br>
&gt; &gt; 8  1  2  2    4<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt; &gt; gen(y,xSum=<br>
&gt; &gt; sum(x1), by=c(&#39;x2&#39;,&#39;x3&#39;) )<br>
&gt; &gt;<br>
&gt; &gt;   x1 x2 x3 xSum<br>
&gt; &gt; 1  1  1  1    2<br>
&gt; &gt; 2  1  1  1    2<br>
&gt; &gt;<br>
&gt; &gt; 3  1  1  2    2<br>
&gt; &gt; 4  1  1  2    2<br>
&gt; &gt; 5  1  2  1    2<br>
&gt; &gt; 6  1  2  1    2<br>
&gt; &gt; 7  1  2  2    2<br>
&gt; &gt; 8  1  2  2    2<br>
&gt; &gt;<br>
&gt; &gt; This is the last Matthew and friends came up with<br>
&gt; &gt; for data.tables:<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt; &gt;<br>
&gt; &gt; require(data.table)<br>
&gt; &gt;<br>
&gt; &gt; &gt;<br>
&gt; &gt; x = data.table(x1 = as.integer(1),<br>
&gt; &gt;  x2 = as.integer(rep(c(1,2), each=2)), x3=<br>
&gt; &gt; as.integer(rep(c(1,2),4)))<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt; &gt;<br>
&gt; &gt; gen2 &lt;- function(data,by,...) {<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; eval(parse(text=paste(&quot;data[,transform(.SD,...),by=&quot;,substitute(by),&quot;]&quot;)))<br>
&gt; &gt;<br>
&gt; &gt;  }<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt; &gt;<br>
&gt; &gt; gen2(x, by=&#39;x2&#39;, xSum = sum(x1)) <br>
&gt; &gt;<br>
&gt; &gt;      x2 x1 x2.1 x3 xSum<br>
&gt; &gt; [1,]  1 <br>
&gt; &gt; 1    1  1    4<br>
&gt; &gt;<br>
&gt; &gt; [2,] <br>
&gt; &gt; 1  1    1  2    4<br>
&gt; &gt; [3,]  1 <br>
&gt; &gt; 1    1  1    4<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt; [4,]  1  1    1  2    4<br>
&gt; &gt; [5,]  2 <br>
&gt; &gt; 1    2  1    4<br>
&gt; &gt; [6,]  2  1    2  2    4<br>
&gt; &gt;<br>
&gt; &gt; [7,] <br>
&gt; &gt; 2  1    2  1    4<br>
&gt; &gt; [8,]  2 <br>
&gt; &gt; 1    2  2    4<br>
&gt; &gt;<br>
&gt; &gt; &gt;<br>
&gt; &gt; gen2(x, by=x2, xSum = sum(x1))     #<br>
&gt; &gt; ok<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt; &gt; gen2(x,<br>
&gt; &gt; by=list(x2,x3), xSum = sum(x1)) #fails<br>
&gt; &gt;<br>
&gt; &gt; Error in `[.data.table`(data, , +gen(.SD, ...), by =<br>
&gt; list)<br>
&gt; &gt; :<br>
&gt; &gt;<br>
&gt; &gt;   column 1 of &#39;by&#39; list does not evaluate to<br>
&gt; &gt; integer e.g. the by should be a list of expressions.<br>
&gt; Do not<br>
&gt; &gt; quote column names when using by=list(...).<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt; &gt;<br>
&gt; &gt; class(x$x2)<br>
&gt; &gt; [1] &quot;integer&quot;<br>
&gt; &gt;<br>
&gt; &gt; &gt;<br>
&gt; &gt; gen2(x, by=c(&#39;x2&#39;,&#39;x3&#39;), xSum = sum(x1))<br>
&gt; &gt; #fails<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt; &gt; gen2(x,<br>
&gt; &gt; by=list(&#39;x2&#39;,&#39;x3&#39;), xSum = sum(x1))<br>
&gt; &gt; #fails<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt; The first issue is that when there are multiple<br>
&gt; grouping<br>
&gt; &gt; factors, passing those to the data.table through this<br>
&gt; &gt; function leads to hangups (see last few example).<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt; The second issue is less critical, but important<br>
&gt; still. The<br>
&gt; &gt; data column x2.1 is automatically added and is<br>
&gt; redundant. <br>
&gt; &gt; With multiple uses of this function, these redundant<br>
&gt; columns<br>
&gt; &gt; add up quickly. I recall that there used to be a way<br>
&gt; to<br>
&gt; &gt; suppress the repeating of columns in this type of<br>
&gt; operation,<br>
&gt; &gt; but it was removed in later versions of data.table.<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt; ~~~~~~~~~~~~<br>
&gt; &gt;<br>
&gt; &gt; There were a few other things Matthew and I were<br>
&gt; &gt; discussing, including alternative &#39;SQL inspired&#39;<br>
&gt; &gt; functions such as &#39;groupby&#39;, &#39;orderby&#39;,<br>
&gt; &gt; &#39;where&#39;, &#39;select&#39;, etc.. I find that<br>
&gt; &gt; functions are a lot easier to remember than syntax,<br>
&gt; for the<br>
&gt; &gt; same reasons natural language syntax is difficult to<br>
&gt; learn<br>
&gt; &gt; compared to learning words. Another selfish reason is<br>
&gt; that<br>
&gt; &gt; SQL was what I and many others learned with<br>
&gt; originally, and<br>
&gt; &gt; the SQL commands would be easier to translate.<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt; On Mon, Jul 12, 2010 at 2:28 PM,<br>
&gt; &gt; Matthew Dowle &lt;<a href="mailto:mdowle@mdowle.plus.com">mdowle@mdowle.plus.com</a>&gt;<br>
&gt; &gt; wrote:<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt; Hi,<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt; There was a thread on r-help where Hadley and I<br>
&gt; discussed<br>
&gt; &gt; plyr using<br>
&gt; &gt;<br>
&gt; &gt; data.table but something technical prevented it at<br>
&gt; that<br>
&gt; &gt; time as I<br>
&gt; &gt;<br>
&gt; &gt; recall. Might be different now. The spelling is<br>
&gt; Wickham.<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt; There is a link on the homepage to the datatable-help<br>
&gt; &gt; subscription<br>
&gt; &gt;<br>
&gt; &gt; page :<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt; <a href="http://datatable.r-forge.r-project.org/" target="_blank">http://datatable.r-forge.r-project.org/</a><br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt; Would be great to see you on that. You explained to me<br>
&gt; once<br>
&gt; &gt; about the<br>
&gt; &gt;<br>
&gt; &gt; functional style I think and I mean to come back to<br>
&gt; it.<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt; Best of luck with your diss,<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt; Matthew<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt; --<br>
&gt; &gt; Sasha Goodman<br>
&gt; &gt; Doctoral Candidate, Organizational Behavior<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt; -----Inline Attachment Follows-----<br>
&gt; &gt;<br>
&gt; &gt; _______________________________________________<br>
&gt; &gt; datatable-help mailing list<br>
&gt; &gt; <a href="mailto:datatable-help@lists.r-forge.r-project.org">datatable-help@lists.r-forge.r-project.org</a><br>
&gt; &gt; <a href="https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/datatable-help" target="_blank">https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/datatable-help</a><br>
&gt; &gt;<br>
&gt;<br>
&gt;<br>
&gt;      <br>
&gt; _______________________________________________<br>
&gt; datatable-help mailing list<br>
&gt; <a href="mailto:datatable-help@lists.r-forge.r-project.org">datatable-help@lists.r-forge.r-project.org</a><br>
&gt; <a href="https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/datatable-help" target="_blank">https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/datatable-help</a><br>
&gt;<br>
<br>
<br>
<br>
</div></div></blockquote></div><br><br clear="all"><br>-- <br>Sasha Goodman<br>Doctoral Candidate, Organizational Behavior<br>