如何编写一个函数调用一个函数调用data.table? [英] How to write a function that calls a function that calls 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 thei
andj
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 wrapperplotfoo()
that callsfoo()
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()
inplotfoo()
looks like one of the following:foo(data, eval(by)) foo(data, by)
When
foo
processes those calls, it dutifullysubstitute
s for the second formal argument (by
) getting asby
's value the symbolseval(by)
orby
. But you wantby
's value to begear
, as in the callfoo(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 itby
, it evaluates it to its value (the symbolgear
) before constructing a call that looks (essentially) like this:foo(data, gear)
这篇关于如何编写一个函数调用一个函数调用data.table?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!