如何编写一个函数调用一个函数调用data.table? [英] How to write a function that calls a function that calls data.table?

查看:127
本文介绍了如何编写一个函数调用一个函数调用data.table?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

data.table 有一些特殊语法,需要使用表达式作为 i j 参数。



这对于一个写函数如何接受和传递参数到数据表有一些启示,在常见问题解答的第1.16节中有效。



但我不知道如何采取这一个额外的水平。



这里是一个例子。说我想写一个包装器函数 foo(),它使我的数据的特定摘要,然后第二个包装 plotfoo()调用 foo()并绘制结果:

  library(data.table)


foo< - function(data,by){
由< - substitute(by)
data [,。 N,by = list(eval(by))]
}

DT< - data.table(mtcars)
foo(DT,gear)

确定,这是有效的,因为我得到了列表结果:

 由N 
1:4 12
2:3 15
3:5 5






现在,我尝试使用 plotfoo

  plotfoo < -  function(data,by){
by& replace(by)
foo(data,eval(by))
}
plotfoo(DT,gear)

但这次我收到一条错误消息:

 错误:评估嵌套太深:无限递归/ options(expressions =)? 






eval()导致问题。让我们删除它:

  plotfoo<  -  function(data,by){
由< - substitute )
foo(data,by)
}
plotfoo(DT,gear)

不,我得到一个新的错误信息:

 错误`[.data.table ,.N,by = list(eval(by))):
'by'或'keyby'的表达式1是类型符号。不要引用列名称。 Useage:DT [,sum(colC),by = list(colA,month(colB))]






这里是我坚持的地方。



问题:如何编写一个函数,调用data.table?

解决方案

这将工作:

  plotfoo<  -  function(data,by){
由< - substitute(by)
do.call(foo,list ),by))
}

plotfoo(DT,gear)
#由N
#1:4 12
#2:3 15
#3:5 5

说明:

问题是你对 foo() plotfoo()看起来像以下之一:

  foo(data,eval(by))
foo )

foo 处理这些调用时dutifully 第二个正式参数替换 s(通过)获取<$ c $ 的符号 c $ c>。但是你需要通过的值为齿轮,如调用 foo ,gear)



do.call()它的第二个参数的元素,然后构造它然后评估的调用。因此,当您通过通过时,它会将其评估为其值(符号 gear ),然后构造(基本上)像这样的调用:

  foo(data,gear)


The package data.table has some special syntax that requires one to use expressions as the i and j arguments.

This has some implications for how one write functions that accept and pass arguments to data tables, as is explained really well in section 1.16 of the FAQs.

But I can't figure out how to take this one additional level.

Here is an example. Say I want to write a wrapper function foo() that makes a specific summary of my data, and then a second wrapper plotfoo() that calls foo() and plots the result:

library(data.table)


foo <- function(data, by){
  by <- substitute(by)
  data[, .N, by=list(eval(by))]
}

DT <- data.table(mtcars)
foo(DT, gear)

OK, this works, because I get my tabulated results:

   by  N
1:  4 12
2:  3 15
3:  5  5


Now, I try to just the same when writing plotfoo() but I fail miserably:

plotfoo <- function(data, by){
  by <- substitute(by)
  foo(data, eval(by))
}
plotfoo(DT, gear)

But this time I get an error message:

Error: evaluation nested too deeply: infinite recursion / options(expressions=)?


OK, so the eval() is causing a problem. Let's remove it:

plotfoo <- function(data, by){
  by <- substitute(by)
  foo(data, by)
}
plotfoo(DT, gear)

Oh no, I get a new error message:

Error in `[.data.table`(data, , .N, by = list(eval(by))) : 
  column or expression 1 of 'by' or 'keyby' is type symbol. Do not quote column names. Useage: DT[,sum(colC),by=list(colA,month(colB))]


And here is where I remain stuck.

Question: How to write a function that calls a function that calls data.table?

解决方案

This will work:

plotfoo <- function(data, by) {
  by <- substitute(by)
  do.call(foo, list(quote(data), by))
}

plotfoo(DT, gear)
#    by  N
# 1:  4 12
# 2:  3 15
# 3:  5  5

Explanation:

The problem is that your call to foo() in plotfoo() looks like one of the following:

foo(data, eval(by))
foo(data, by)

When foo processes those calls, it dutifully substitutes for the second formal argument (by) getting as by's value the symbols eval(by) or by. But you want by's value to be gear, as in the call foo(data, gear).

do.call() solves this problem by evaluating the elements of its second argument before constructing the call that it then evaluates. As a result, when you pass it by, it evaluates it to its value (the symbol gear) before constructing a call that looks (essentially) like this:

foo(data, gear)

这篇关于如何编写一个函数调用一个函数调用data.table?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆