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

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

问题描述

data.table 包有一些特殊的语法,需要使用表达式作为 ij 参数.

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

这对于如何编写接受参数并将参数传递给数据表的函数有一些影响,正如 常见问题解答第 1.16 节.

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.

这是一个例子.假设我想编写一个包装器函数 foo() 来对我的数据进行特定的汇总,然后再编写一个调用 foo() 的包装器 plotfoo() 并绘制结果:

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

<小时>

现在,我在编写 plotfoo() 时尝试相同,但我失败了:


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=)?

<小时>

好的,所以 eval() 引起了问题.让我们删除它:


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.

问题:如何编写调用data.table的函数的函数?

推荐答案

这将起作用:

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

说明:

问题是您在 plotfoo() 中对 foo() 的调用类似于以下内容之一:

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

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

foo 处理这些调用时,它会尽职尽责地 substitute 代替 第二个形式参数 (by)作为 byvalue 符号 eval(by)by.但是你希望 by 的值是 gear,就像在调用 foo(data, gear) 中一样.

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() 解决了这个问题,方法是在构造它然后评估的调用之前评估其第二个参数的元素.因此,当您通过 by 传递它时,它会在构造一个看起来(基本上)如下所示的调用之前将其评估为它的值(符号 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天全站免登陆