<br><br><div class="gmail_quote">On 20 July 2011 10:42, Matthew Dowle <span dir="ltr">&lt;<a href="mailto:mdowle@mdowle.plus.com">mdowle@mdowle.plus.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">

<br>
Thanks, makes sense. Yes, as.data.frame.data.table currently removes the<br>
&#39;sorted&#39; attribute, which is all a key is. I suppose that line could be<br>
removed so the key would be left on the data.frame.  You would then need<br>
to change the class back to data.table at the end of the function, though,<br>
and make sure you didn&#39;t change the order of the rows otherwise that key<br>
would be invalid.<br>
<br>
However, packages I use, use other packages I don&#39;t use directly and know<br>
nothing about. I don&#39;t see the issue. Disk space? Memory space? The<br>
banner?<br></blockquote><div><br></div><div>Behaving nicely in a build environment that is more complicated than a normal R thing.  </div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">


There is also this related FR :<br>
<a href="https://r-forge.r-project.org/tracker/index.php?func=detail&amp;aid=984&amp;group_id=240&amp;atid=978" target="_blank">https://r-forge.r-project.org/tracker/index.php?func=detail&amp;aid=984&amp;group_id=240&amp;atid=978</a><br>


<br>
Just to check you know that the result of j in data.table can happily be a<br>
data.frame?  So if your user is using data.table to call your function, he<br>
won&#39;t mind. If he&#39;s passing the entire data.table to your function, then<br>
he&#39;s not going to be wanting to retain the key anyway. You&#39;re returning<br>
some statistical result to him (not the orginal data back) so why does the<br>
key make sense to retain?<br>
<br></blockquote><div><br></div><div>Well I explicitly crafted an example where I return the entire data frame.  Now, in this dumb example I ruined the ordering so the key leaves anyway.  But I think i have cases where I want to take an entire data.(table|frame), do some processing, and return the full data.(table|frame) back like it was.</div>

<div><br></div><div> Noticing that strictly, your MyFunc &#39;returned&#39; two columns, so it might be</div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
written like this :<br>
<br>
MyFunc &lt;- function(numerator,denominator)<br>
{<br>
     o = order(numerator)<br>
     data.frame(numerator[o], cumsum((numerator/denomintor)[o])<br>
}<br>
<br>
Then the user can decide if he wants to cbind it to his data.frame, or<br>
fast assign it into a data.table,  or by group,  or whatever.  That seems<br>
to me to be up to your user.  Perhaps, the job of MyFunc is to return it&#39;s<br>
output given the input (and that&#39;s all).<br></blockquote><div><br></div><div><br></div><div>I think my issues are coming more from inexperience/uneasiness with some of the data.table idioms still. When you list it all out like that it becomes crystal clear though, and I think refactoring of my code is correct.  I&#39;m just not in the data.table mindset yet I guess.</div>

<div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;"><font color="#888888">
Matthew<br>
</font><div><div></div><div class="h5"><br>
<br>
&gt; Mainly it is that I am writing some library functions that I and a few<br>
&gt; others may be using. I don&#39;t want those functions to have to depend on<br>
&gt; data.table because I don&#39;t want it to need to be installed for a purpose<br>
&gt; that has nothing to do with it. But I use data.tables as input. Here is a<br>
&gt; psuedo example<br>
&gt;<br>
&gt; MyFunc &lt;- function(data, numerator.var, denominator.var)<br>
&gt; {<br>
&gt;   data &lt;- data[order(data[,numerator.var])]<br>
&gt;   data$metric &lt;- data[, numerator.var] / data[, denominator.var]<br>
&gt;   data$cum.metric &lt;- cumsum(data$metric)<br>
&gt;<br>
&gt;   return(data)<br>
&gt; }<br>
&gt;<br>
&gt; I make this example to show that I need to preserve the whole data<br>
&gt; variable<br>
&gt; the whole way through and return a modified version.  If I do<br>
&gt;<br>
&gt; data &lt;- as.data.frame(data)<br>
&gt;<br>
&gt; as the first line of that function, then I lose the keys in a potential<br>
&gt; data.table that is passed in.  If I use<br>
&gt;<br>
&gt; data &lt;- as.data.table(data)<br>
&gt;<br>
&gt; and change the subsetting to be data.table compliant, then I am forcing<br>
&gt; someone to have a whole package loaded for something that can be done in<br>
&gt; the<br>
&gt; base language fine. There must be an agnostic way to do this. Apparently<br>
&gt; subset doesn&#39;t do it either if keys get lost.<br>
&gt;<br>
&gt; -Chris<br>
&gt;<br>
&gt; On 20 July 2011 08:48, Matthew Dowle &lt;<a href="mailto:mdowle@mdowle.plus.com">mdowle@mdowle.plus.com</a>&gt; wrote:<br>
&gt;<br>
&gt;&gt;<br>
&gt;&gt; Hi Chris,<br>
&gt;&gt;<br>
&gt;&gt; If you&#39;re writing a package and don&#39;t want to worry if someone passes<br>
&gt;&gt; your<br>
&gt;&gt; package a data.table, then don&#39;t worry; just use data.frame syntax and<br>
&gt;&gt; your non-datatable-aware package will work fine.<br>
&gt;&gt;<br>
&gt;&gt; If you&#39;re writing your own code you&#39;re in control of, just embrace the<br>
&gt;&gt; data.table ;)<br>
&gt;&gt;<br>
&gt;&gt; If you&#39;re writing a function in an environment which is data.table<br>
&gt;&gt; aware,<br>
&gt;&gt; but you want your function to accept either data.frame or data.table,<br>
&gt;&gt; then<br>
&gt;&gt; at the beginning of your function just do :<br>
&gt;&gt;<br>
&gt;&gt; f = myfunction(x) {<br>
&gt;&gt;    x = as.data.table(x)<br>
&gt;&gt;    # proceed with data.table syntax<br>
&gt;&gt; }<br>
&gt;&gt;<br>
&gt;&gt; or<br>
&gt;&gt;<br>
&gt;&gt; f = myfunction(x) {<br>
&gt;&gt;    x = as.data.frame(x)<br>
&gt;&gt;    # proceed with data.frame syntax<br>
&gt;&gt; }<br>
&gt;&gt;<br>
&gt;&gt; Some of the CRAN packages that depend on data.table are doing that, I<br>
&gt;&gt; think.<br>
&gt;&gt;<br>
&gt;&gt; In R itself it is common practice to coerce arguments to a common type<br>
&gt;&gt; and<br>
&gt;&gt; then proceed with the appropriate syntax for that type.  Consider that<br>
&gt;&gt; matrix syntax is different syntax to data.frame syntax. You often see<br>
&gt;&gt; as.classiwant() at the beginning of functions, or switches depending on<br>
&gt;&gt; the type of object.<br>
&gt;&gt;<br>
&gt;&gt; Remember that is.data.frame() is TRUE for both data.frame and<br>
&gt;&gt; data.table,<br>
&gt;&gt; but is.data.table() is TRUE only for data.table.  as.data.table() does<br>
&gt;&gt; nothing if x is already a data.table, and is an efficient class change<br>
&gt;&gt; if<br>
&gt;&gt; x is a data.frame.  Is efficiency the issue?<br>
&gt;&gt;<br>
&gt;&gt; Does that help?  If not, more info about the problem will be needed<br>
&gt;&gt; please.<br>
&gt;&gt;<br>
&gt;&gt; Matthew<br>
&gt;&gt;<br>
&gt;&gt;<br>
&gt;&gt; &gt; I&#39;m used to seeing the column names at the bottom of the column too,<br>
&gt;&gt; but<br>
&gt;&gt; &gt; that is only if the data.table is long enough. My example was too<br>
&gt;&gt; short<br>
&gt;&gt; &gt; for<br>
&gt;&gt; &gt; that, so I made the same sort of mistake you did :(<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt; Okay, that is a way, but is it a good way? Not sure...<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt; 2011/7/20 Timothée Carayol &lt;<a href="mailto:timothee.carayol@gmail.com">timothee.carayol@gmail.com</a>&gt;<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt;&gt; Sorry my mistake -- subset does return a data.table.<br>
&gt;&gt; &gt;&gt; (I was using as an example a data.table with 100 rows, and stupidly<br>
&gt;&gt; &gt;&gt; using<br>
&gt;&gt; &gt;&gt; the fact that it printed the whole thing rather than the 10 first<br>
&gt;&gt; rows<br>
&gt;&gt; &gt;&gt; only<br>
&gt;&gt; &gt;&gt; as my criterion for whether it worked or not.. Omitting that<br>
&gt;&gt; &gt;&gt; print.data.table does print up to 100 rows. I feel a bit stupid.)<br>
&gt;&gt; &gt;&gt;<br>
&gt;&gt; &gt;&gt; Why doesn&#39;t it work for you if that is the case?<br>
&gt;&gt; &gt;&gt;<br>
&gt;&gt; &gt;&gt; DF &lt;- data.frame(a=1:200, b=1:10)<br>
&gt;&gt; &gt;&gt; DT &lt;- as.data.table(DF)<br>
&gt;&gt; &gt;&gt; subDT &lt;- subset(DT, select=a)<br>
&gt;&gt; &gt;&gt; class(DT)<br>
&gt;&gt; &gt;&gt; subDF &lt;- subset(DF, select=a)<br>
&gt;&gt; &gt;&gt; class(DF)<br>
&gt;&gt; &gt;&gt; identical(as.data.frame(DT), DF)<br>
&gt;&gt; &gt;&gt;<br>
&gt;&gt; &gt;&gt;<br>
&gt;&gt; &gt;&gt;<br>
&gt;&gt; &gt;&gt; On Wed, Jul 20, 2011 at 12:50 PM, Chris Neff &lt;<a href="mailto:caneff@gmail.com">caneff@gmail.com</a>&gt;<br>
&gt;&gt; wrote:<br>
&gt;&gt; &gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt; Yeah I realized that myself.<br>
&gt;&gt; &gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt; Another one: the function &quot;with&quot; doesn&#39;t seem to do what I want...<br>
&gt;&gt; but<br>
&gt;&gt; &gt;&gt;&gt; at<br>
&gt;&gt; &gt;&gt;&gt; least it is consistent!<br>
&gt;&gt; &gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt; 2011/7/20 Timothée Carayol &lt;<a href="mailto:timothee.carayol@gmail.com">timothee.carayol@gmail.com</a>&gt;<br>
&gt;&gt; &gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;&gt; Sorry --<br>
&gt;&gt; &gt;&gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;&gt; subset() was a poor idea, as it will return a data.frame even if<br>
&gt;&gt; the<br>
&gt;&gt; &gt;&gt;&gt;&gt; argument is a data.table..<br>
&gt;&gt; &gt;&gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;&gt; 2011/7/20 Timothée Carayol &lt;<a href="mailto:timothee.carayol@gmail.com">timothee.carayol@gmail.com</a>&gt;<br>
&gt;&gt; &gt;&gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;&gt;&gt; Hi--<br>
&gt;&gt; &gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;&gt;&gt; You can use the subset() command with the select= option; not sure<br>
&gt;&gt; &gt;&gt;&gt;&gt;&gt; it&#39;s<br>
&gt;&gt; &gt;&gt;&gt;&gt;&gt; the best solution, though.<br>
&gt;&gt; &gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;&gt;&gt; Timothee<br>
&gt;&gt; &gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;&gt;&gt; On Wed, Jul 20, 2011 at 12:26 PM, Chris Neff &lt;<a href="mailto:caneff@gmail.com">caneff@gmail.com</a>&gt;<br>
&gt;&gt; &gt;&gt;&gt;&gt;&gt; wrote:<br>
&gt;&gt; &gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;&gt;&gt;&gt; I have a function where I pass a data frame and some variable<br>
&gt;&gt; names<br>
&gt;&gt; &gt;&gt;&gt;&gt;&gt;&gt; to<br>
&gt;&gt; &gt;&gt;&gt;&gt;&gt;&gt; calculate statistics on. However, I am at a loss as to how to<br>
&gt;&gt; write<br>
&gt;&gt; &gt;&gt;&gt;&gt;&gt;&gt; it<br>
&gt;&gt; &gt;&gt;&gt;&gt;&gt;&gt; correctly so that both data.frame and data.table work with it. If<br>
&gt;&gt; I<br>
&gt;&gt; &gt;&gt;&gt;&gt;&gt;&gt; have:<br>
&gt;&gt; &gt;&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;&gt;&gt;&gt; DF = data.frame(x=1:10,y=2:11,z=3:12)<br>
&gt;&gt; &gt;&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;&gt;&gt;&gt; DT = data.table(DF)<br>
&gt;&gt; &gt;&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;&gt;&gt;&gt; var.names = c(&quot;x&quot;,&quot;y&quot;)<br>
&gt;&gt; &gt;&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;&gt;&gt;&gt; I can do the following things to subset:<br>
&gt;&gt; &gt;&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;&gt;&gt;&gt; DT[,var.names,with=FALSE]<br>
&gt;&gt; &gt;&gt;&gt;&gt;&gt;&gt; DF[,var.names]<br>
&gt;&gt; &gt;&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;&gt;&gt;&gt; but of course DT[,var.names] won&#39;t give me back what I want, and<br>
&gt;&gt; &gt;&gt;&gt;&gt;&gt;&gt; DF[,var.names,with=FALSE] returns an error because with doesn&#39;t<br>
&gt;&gt; &gt;&gt;&gt;&gt;&gt;&gt; exist there.<br>
&gt;&gt; &gt;&gt;&gt;&gt;&gt;&gt; So how do I do this?<br>
&gt;&gt; &gt;&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;&gt;&gt;&gt; Thanks,<br>
&gt;&gt; &gt;&gt;&gt;&gt;&gt;&gt; -Chris<br>
&gt;&gt; &gt;&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;&gt;&gt;&gt; _______________________________________________<br>
&gt;&gt; &gt;&gt;&gt;&gt;&gt;&gt; datatable-help mailing list<br>
&gt;&gt; &gt;&gt;&gt;&gt;&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; &gt;&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;&gt;&gt;&gt;<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; &gt;&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;<br>
&gt;&gt; &gt; _______________________________________________<br>
&gt;&gt; &gt; datatable-help mailing list<br>
&gt;&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; &gt;<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; &gt;<br>
&gt;&gt;<br>
&gt;&gt;<br>
&gt;&gt;<br>
&gt;<br>
<br>
<br>
</div></div></blockquote></div><br>