Just chiming in to say something similar to colwise from plyr would be quite nice. You could just carry around a vector of variable names, then do something DT[ ,colwise( f, var_names), by=by_names ].<div><br></div><div><br>

<div class="gmail_quote">On 15 July 2011 14:06, Dennis Murphy <span dir="ltr">&lt;<a href="mailto:djmuser@gmail.com">djmuser@gmail.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">

<div class="im">On Fri, Jul 15, 2011 at 8:23 AM, Steve Lianoglou<br>
&lt;<a href="mailto:mailinglist.honeypot@gmail.com">mailinglist.honeypot@gmail.com</a>&gt; wrote:<br>
&gt; Hi Dennis,<br>
&gt;<br>
&gt; I didn&#39;t see your post before I sent my latest reply.<br>
&gt;<br>
&gt; Nice detective work!<br>
<br>
</div>Thanks, Steve. I just followed my nose and the docs, which I have<br>
conveniently kept in a small binder for such occasions :) Like JV, I<br>
don&#39;t use data.table every day, so some of its idiosyncracies get<br>
cobwebbed in the hard drive over time. The wiki entries helped a lot.<br>
<div class="im"><br>
&gt;<br>
&gt; For what it&#39;s worth, from what I understand your<br>
&gt; &quot;punchline&quot;/kewpie-prize solution is so much faster because it avoids<br>
&gt; building the .SD data.table within each group.<br>
<br>
</div>That was my deduction from having read the first entry in the wiki. I<br>
still can&#39;t believe I got that thing to work :)<br>
<div class="im"><br>
&gt;<br>
&gt; I&#39;ll let Matthew leave a more detailed comment, since he&#39;s (obviously)<br>
&gt; much more intimately familiar w/ the inner voodoo of data.table. But<br>
&gt; as a last comment -- if the speed differences are so drastic because<br>
&gt; of the cost of creating the .SD data.table, maybe we should think<br>
&gt; about taking some &quot;inspiration&quot; from plyr and define a similar<br>
&gt; `colwise` function -- which would operate across each &quot;column&quot; of<br>
&gt; supposedly-build .SD object applying a function to each of them w/o<br>
&gt; actually building an .SD object itself.<br>
<br>
</div>Your clairvoyance skills are clearly operating today :)  More<br>
seriously, this is what I would consider an &#39;obvious&#39; &quot;big-data&quot;<br>
problem - I could easily see situations arising in finance and genomic<br>
applications where a fairly large subset of variables of the same<br>
type, but not necessarily all of them, need to be summarized in a<br>
particular way. The colwise() functions would be problematic as well<br>
in the scenario described in my eariler post, but I haven&#39;t tried<br>
ddply() to verify that assertion so I could be mistaken.<br>
<br>
It would be *really* helpful to have a convenient, fast  mechanism in<br>
data.table that allows one to substitute a (possibly large) vector of<br>
variable names into a function. Alas, I don&#39;t have any bright ideas<br>
about how to program it. Fortunately, there are some nice functions in<br>
R to select variable subsets efficiently in data frames (e.g., the<br>
grep() family of functions, regular expressions, %in% and so on), but<br>
I don&#39;t know how that would translate easily to data.table() since the<br>
internals are so different.<br>
<br>
Looking forward to the team&#39;s take on this...<br>
<font color="#888888"><br>
Dennis<br>
</font><div><div></div><div class="h5"><br>
&gt;<br>
&gt; -steve<br>
&gt;<br>
&gt; On Fri, Jul 15, 2011 at 10:34 AM, Dennis Murphy &lt;<a href="mailto:djmuser@gmail.com">djmuser@gmail.com</a>&gt; wrote:<br>
&gt;&gt; Hi:<br>
&gt;&gt;<br>
&gt;&gt; &lt;A bunch snipped because I get the archives in digest form&gt;<br>
&gt;&gt;<br>
&gt;&gt; Re Prof. Voelkel&#39;s recent posts:<br>
&gt;&gt;<br>
&gt;&gt; (1) Quoting does not work well in data.table; this is mentioned in<br>
&gt;&gt; several of the FAQs. Apropos to this discussion, some of the relevant<br>
&gt;&gt; ones include 1.2, 1.6 and 2.1; there may be others :)<br>
&gt;&gt;<br>
&gt;&gt; (2) Steve&#39;s response seems to be the right way to go (although see<br>
&gt;&gt; below), but I thought I&#39;d up the stakes a little and assume that Prof.<br>
&gt;&gt; Voelkel has a large number of variables, only a subset of which he may<br>
&gt;&gt; want summarized in a particular go. To that end, I created the<br>
&gt;&gt; following toy data frame cum data.table; this is as much for my own<br>
&gt;&gt; edification as anyone else&#39;s (which explains the eventual length of<br>
&gt;&gt; this post...I got curious :)<br>
&gt;&gt;<br>
&gt;&gt; This goes against the advice given in the first example of the<br>
&gt;&gt; data.table wiki, but if you have, say, 100 variables to select out of<br>
&gt;&gt; a possible 1000, it doesn&#39;t make sense to list them individually as<br>
&gt;&gt; recommended on the wiki. (But see below...)<br>
&gt;&gt;<br>
&gt;&gt; library(&#39;data.table&#39;)<br>
&gt;&gt; set.seed(1043)<br>
&gt;&gt; m &lt;- matrix(rpois(240, 10), nrow = 6)<br>
&gt;&gt; colnames(m) &lt;- paste(&#39;A&#39;, 1:40, sep = &#39;&#39;)<br>
&gt;&gt; m &lt;- as.data.frame(m)<br>
&gt;&gt; dt2 &lt;- data.table(x = rep(1:3, 2), y = rep(1:3, each = 2), m, key = &#39;x&#39;)<br>
&gt;&gt; dim(dt2)<br>
&gt;&gt; # [1]  6 42       ...so far, so good<br>
&gt;&gt;<br>
&gt;&gt; # Subset of variables for which sums are desired<br>
&gt;&gt; vars &lt;- paste(&#39;A&#39;, c(1, 4, 10, 15, 31), sep = &#39;&#39;)<br>
&gt;&gt;<br>
&gt;&gt; # One approach: use the select = argument of subset() to restrict<br>
&gt;&gt; # the variables under consideration:<br>
&gt;&gt; dt2[, lapply(subset(.SD, select = vars), sum), by = &#39;x&#39;]<br>
&gt;&gt;     x A1 A4 A10 A15 A31<br>
&gt;&gt; [1,] 1 18 21  22  22  24<br>
&gt;&gt; [2,] 2 20 13 27 23 21<br>
&gt;&gt; [3,] 3 22 15  16  23  15<br>
&gt;&gt;<br>
&gt;&gt; # Use the with = FALSE construct of data.table to do the same:<br>
&gt;&gt; dt2[, lapply(.SD[, vars, with = FALSE], sum), by = &#39;x, y&#39;]<br>
&gt;&gt;     x y A1 A4 A10 A15 A31<br>
&gt;&gt; [1,] 1 1 11 13  12  11  16<br>
&gt;&gt; [2,] 1 2  7  8  10  11   8<br>
&gt;&gt; [3,] 2 1 10  4  16   7  11<br>
&gt;&gt; [4,] 2 3 10 9 11 16 10<br>
&gt;&gt; [5,] 3 2 11  8   7  11   7<br>
&gt;&gt; [6,] 3 3 11  7   9  12   8<br>
&gt;&gt;<br>
&gt;&gt; # For this example, it is the same (apart from the key variables) as<br>
&gt;&gt; dt2[, vars, with = FALSE]<br>
&gt;&gt;<br>
&gt;&gt; Not bad for this small example, but what happens in a much larger data table?<br>
&gt;&gt;<br>
&gt;&gt; To find out, I created a 10000 x 1000 matrix that I converted into a<br>
&gt;&gt; data table, added two grouping variables of 100 levels each and then<br>
&gt;&gt; tried both approaches above again. Performance isn&#39;t bad when<br>
&gt;&gt; summarizing over one variable, but there is a definite hit when two<br>
&gt;&gt; variables are summarized. [It makes some sense since one is grouping<br>
&gt;&gt; over 10000 level combinations rather than 100, but once again, keep<br>
&gt;&gt; reading.] Curiously, it makes no difference if there is one key<br>
&gt;&gt; variable or two, which made me wonder what the preferred approach is<br>
&gt;&gt; in this circumstance.<br>
&gt;&gt;<br>
&gt;&gt; m &lt;- matrix(rpois(10000000, 10), nrow = 10000)<br>
&gt;&gt; m &lt;- as.data.table(m)<br>
&gt;&gt; m &lt;- transform(m, x = rep(1:100, each = 100), y = rep(1:100, 100))<br>
&gt;&gt; setkey(m, &#39;x&#39;)<br>
&gt;&gt; dim(m)<br>
&gt;&gt; # [1] 10000  1002<br>
&gt;&gt;<br>
&gt;&gt; # Randomly select 150 variables from the 1000<br>
&gt;&gt; vars &lt;- paste(&#39;A&#39;, sample(1:1000, 150, replace = FALSE), sep = &#39;&#39;)<br>
&gt;&gt; length(vars)<br>
&gt;&gt; # [1] 150<br>
&gt;&gt; key(m)<br>
&gt;&gt; # [1] &quot;x&quot;<br>
&gt;&gt;&gt; system.time(m[, lapply(subset(.SD, select = vars), sum), by = &#39;x&#39;])<br>
&gt;&gt;   user  system elapsed<br>
&gt;&gt;   0.75    0.00    0.75<br>
&gt;&gt;&gt; system.time(m[, lapply(.SD[, vars, with = FALSE], sum), by = &#39;x&#39;])<br>
&gt;&gt;   user  system elapsed<br>
&gt;&gt;   0.64    0.00    0.64<br>
&gt;&gt;&gt; system.time(m[, lapply(subset(.SD, select = vars), sum), by = &#39;x, y&#39;])<br>
&gt;&gt;   user  system elapsed<br>
&gt;&gt;  53.65    0.00   53.85<br>
&gt;&gt;&gt; system.time(m[, lapply(.SD[, vars, with = FALSE], sum), by = &#39;x, y&#39;])<br>
&gt;&gt;   user  system elapsed<br>
&gt;&gt;  44.21    0.01   44.35<br>
&gt;&gt;<br>
&gt;&gt; m2 &lt;- data.table(m, key = &#39;x, y&#39;)<br>
&gt;&gt; rm(m)<br>
&gt;&gt; key(m2)<br>
&gt;&gt; # [1] &quot;x&quot; &quot;y&quot;<br>
&gt;&gt;&gt; system.time(m2[, lapply(subset(.SD, select = vars), sum), by = &#39;x, y&#39;])<br>
&gt;&gt;   user  system elapsed<br>
&gt;&gt;  53.54    0.00   53.73<br>
&gt;&gt;&gt; system.time(m2[, lapply(.SD[, vars, with = FALSE], sum), by = &#39;x, y&#39;])<br>
&gt;&gt;   user  system elapsed<br>
&gt;&gt;  44.30    0.04   44.60<br>
&gt;&gt;<br>
&gt;&gt; The first question in the wiki<br>
&gt;&gt; (<a href="http://rwiki.sciviews.org/doku.php?id=packages:cran:data.table" target="_blank">http://rwiki.sciviews.org/doku.php?id=packages:cran:data.table</a>) says<br>
&gt;&gt; to use the columns directly rather than to rely on .SD. I wanted to<br>
&gt;&gt; know how to pass new names to the summaries instead of overwriting the<br>
&gt;&gt; original variable names. For the fun of it, I tried the following:<br>
&gt;&gt;<br>
&gt;&gt; select &lt;- sample(1:1000, 150, replace = FALSE)<br>
&gt;&gt; vars &lt;- paste(&#39;A&#39;, select, sep = &#39;&#39;)<br>
&gt;&gt; outvars &lt;- paste(&#39;S&#39;, select, sep = &#39;&#39;)<br>
&gt;&gt;<br>
&gt;&gt; # Create a long expression of the form &#39;list(..., Sn = sum(An), ...)&#39;,<br>
&gt;&gt; # n a subscript from 1 to 150.<br>
&gt;&gt; expr &lt;- paste(&#39;list(&#39;, paste(outvars, paste(&#39;sum(&#39;, vars, &#39;)&#39;, sep =<br>
&gt;&gt; &#39;&#39;), sep = &#39;=&#39;, collapse = &#39;,&#39;),<br>
&gt;&gt;               &#39;)&#39;, sep = &#39;&#39;)<br>
&gt;&gt; u &lt;- m2[, eval(parse(text = expr)), by = &#39;x&#39;]<br>
&gt;&gt;&gt; dim(u)<br>
&gt;&gt; # [1] 100 151     seems reasonable...<br>
&gt;&gt;<br>
&gt;&gt; This seemed to run rather fast, so I decided to time it:<br>
&gt;&gt;<br>
&gt;&gt;&gt; system.time(m2[, eval(parse(text = expr)), by = &#39;x&#39;])<br>
&gt;&gt;   user  system elapsed<br>
&gt;&gt;   0.03    0.00    0.03<br>
&gt;&gt;&gt; system.time(m2[, eval(parse(text = expr)), by = &#39;x, y&#39;])<br>
&gt;&gt;   user  system elapsed<br>
&gt;&gt;   1.05    0.00    1.04<br>
&gt;&gt;<br>
&gt;&gt; I&#39;ve got to admit, this is not the approach I would have taken<br>
&gt;&gt; normally, is certainly not intuitively obvious to me and flouts the<br>
&gt;&gt; usual advice to avoid the eval(parse(text = )) mantra, but the data<br>
&gt;&gt; don&#39;t lie :)  Please tell me there&#39;s a more code-efficient way to do<br>
&gt;&gt; this (the new variable names included), because my &#39;solution&#39; was a<br>
&gt;&gt; complete kludge and accidental kewpie prize.<br>
&gt;&gt;<br>
&gt;&gt; Cheers,<br>
&gt;&gt; Dennis<br>
&gt;&gt;<br>
&gt;&gt;&gt; Message: 1<br>
&gt;&gt;&gt; Date: Thu, 14 Jul 2011 16:36:11 -0400<br>
&gt;&gt;&gt; From: Joseph Voelkel &lt;<a href="mailto:jgvcqa@rit.edu">jgvcqa@rit.edu</a>&gt;<br>
&gt;&gt;&gt; Subject: [datatable-help] Skipping some Vi names<br>
&gt;&gt;&gt; To: &quot;<a href="mailto:datatable-help@lists.r-forge.r-project.org">datatable-help@lists.r-forge.r-project.org</a>&quot;<br>
&gt;&gt;&gt;        &lt;<a href="mailto:datatable-help@r-forge.wu-wien.ac.at">datatable-help@r-forge.wu-wien.ac.at</a>&gt;<br>
&gt;&gt;&gt; Message-ID:<br>
&gt;&gt;&gt;        &lt;<a href="mailto:70EFCDD908F9264785FA08EC3A471320282158585C@ex02mail01.ad.rit.edu">70EFCDD908F9264785FA08EC3A471320282158585C@ex02mail01.ad.rit.edu</a>&gt;<br>
&gt;&gt;&gt; Content-Type: text/plain; charset=&quot;us-ascii&quot;<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; I don&#39;t use data.table too much (though I probably should use it more...).<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; I was surprised at the results below. It appears that the name V1 gets assigned to the first result, but then the keys (&quot;in the background&quot;) are assigned the next set of Vi names, creating a gap in the names depending on the number of keys. I would like to see the Vi names appear in their natural, sequential, order. Not a show stopper, but it&#39;s annoying. (I have over 40 Vi&#39;s and it&#39;d be good to have them numbered more rationally.) Thanks.<br>


&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt; dt&lt;-data.table(x=c(1,2,3,1,2,3),y=c(1,1,2,2,3,3),A1=1:6,A2=7:12,A3=13:18,key=&quot;x&quot;)<br>
&gt;&gt;&gt;&gt; dt[,list(&quot;sum(A1),sum(A2),sum(A3)&quot;),by=&quot;x&quot;]<br>
&gt;&gt;&gt;     x V1 V3 V4<br>
&gt;&gt;&gt; [1,] 1  5 17 29<br>
&gt;&gt;&gt; [2,] 2  7 19 31<br>
&gt;&gt;&gt; [3,] 3  9 21 33<br>
&gt;&gt;&gt;&gt; key(dt)&lt;-c(&quot;x&quot;,&quot;y&quot;)<br>
&gt;&gt;&gt;&gt; dt[,list(&quot;sum(A1),sum(A2),sum(A3)&quot;),by=&quot;x,y&quot;]<br>
&gt;&gt;&gt;     x y V1 V4 V5<br>
&gt;&gt;&gt; [1,] 1 1  1  7 13<br>
&gt;&gt;&gt; [2,] 1 2  4 10 16<br>
&gt;&gt;&gt; [3,] 2 1  2  8 14<br>
&gt;&gt;&gt; [4,] 2 3  5 11 17<br>
&gt;&gt;&gt; [5,] 3 2  3  9 15<br>
&gt;&gt;&gt; [6,] 3 3  6 12 18<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; Joseph G. Voelkel, Ph.D.<br>
&gt;&gt;&gt; Professor, Center for Quality and Applied Statistics<br>
&gt;&gt;&gt; Kate Gleason College of Engineering<br>
&gt;&gt;&gt; Rochester Institute of Technology<br>
&gt;&gt;&gt; V 585-475-2231<br>
&gt;&gt;&gt; F 585-475-5959<br>
&gt;&gt;&gt; <a href="mailto:joseph.voelkel@rit.edu">joseph.voelkel@rit.edu</a><br>
&gt;&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; Steve Lianoglou<br>
&gt; Graduate Student: Computational Systems Biology<br>
&gt;  | Memorial Sloan-Kettering Cancer Center<br>
&gt;  | Weill Medical College of Cornell University<br>
&gt; Contact Info: <a href="http://cbio.mskcc.org/~lianos/contact" target="_blank">http://cbio.mskcc.org/~lianos/contact</a><br>
&gt;<br>
_______________________________________________<br>
datatable-help mailing list<br>
<a href="mailto:datatable-help@lists.r-forge.r-project.org">datatable-help@lists.r-forge.r-project.org</a><br>
<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>
</div></div></blockquote></div><br></div>