在函数中使用data.table i和j参数 [英] Using data.table i and j arguments in functions

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

问题描述

我想用 data.table 写一些封装函数来减少代码重复。

I am trying to write some wrapper functions to reduce code duplication with data.table.

使用 mtcars 的示例。首先,设置一些数据:

Here is an example using mtcars. First, set up some data:

data(mtcars)
mtcars$car <- factor(gsub("(.*?) .*", "\\1", rownames(mtcars)), ordered=TRUE)
mtcars <- data.table(mtcars)

现在,这里是我通常写的,以获得组的计数摘要。在这种情况下,我按 car 分组:

Now, here is what I would usually write to get a summary of counts by group. In this case I am grouping by car:

mtcars[, list(Total=length(mpg)), by="car"][order(car)]

      car Total
      AMC     1
 Cadillac     1
   Camaro     1
...
   Toyota     2
  Valiant     1
    Volvo     1

复杂性在于,由于 i j 的参数在 data.table ,如果要传入变量,必须使用 eval(...)

The complication is that, since the arguments i and j are evaluated in the frame of the data.table, one has to use eval(...) if you want to pass in variables:

这个工程:

group <- "car"
mtcars[, list(Total=length(mpg)), by=eval(group)]

想要通过相同的分组变量对结果排序。我不能得到以下的任何变体,给我正确的结果。注意我总是得到单行结果,而不是有序集。

But now I want to order the results by the same grouping variable. I can't get any variant of the following to give me correct results. Notice how I always get a single row of results, rather than the ordered set.

mtcars[, list(Total=length(mpg)), by=eval(group)][order(group)]
   car Total
 Mazda     2

我知道原因:这是因为 group parent.frame data.table 的框架。

I know why: it's because group is evaluated in the parent.frame, not the frame of the data.table.

如何评估 c

How can I evaluate group in the context of the data.table?

更多一般情况下,在 data.table ,我该如何使用这里面的函数?我需要以下函数给我所有的结果,而不只是第一行数据:

More generally, how can I use this inside a function? I need the following function to give me all the results, not just the first row of data:

tableOrder <- function(x, group){
  x[, list(Total=length(mpg)), by=eval(group)][order(group)]
}

tableOrder(mtcars, "car")


推荐答案

Gavin和Josh是对的。这个答案只是为了增加更多的背景。这个想法是,不仅可以使用 quote()将可变列名称传递到这样的函数中,而是的列名称。 / p>

Gavin and Josh are right. This answer is only to add more background. The idea is that not only can you pass variable column names into a function like that, but expressions of column names, using quote().

group = quote(car)
mtcars[, list(Total=length(mpg)), by=group][order(group)]
      group Total
        AMC     1
   Cadillac     1
     ...
     Toyota     2
    Valiant     1
      Volvo     1

虽然,开始更难,但可以更灵活。这是想法,反正。内部函数需要 substitute(),如下所示:

Although, admitedly more difficult to start with, it can be more flexible. That's the idea, anyway. Inside functions you need substitute(), like this :

tableOrder = function(x,.expr) {
    .expr = substitute(.expr)
    ans = x[,list(Total=length(mpg)),by=.expr]
    setkeyv(ans, head(names(ans),-1))    # see below re feature request #1780
    ans
}

tableOrder(mtcars, car)
      .expr Total
        AMC     1
   Cadillac     1
     Camaro     1
      ...
     Toyota     2
    Valiant     1
      Volvo     1

tableOrder(mtcars, substring(car,1,1))  # an expression, not just a column name
      .expr Total
 [1,]     A     1
 [2,]     C     3
 [3,]     D     3
 ...
 [8,]     P     2
 [9,]     T     2
[10,]     V     2

tableOrder(mtcars, list(cyl,gear%%2))   # by two expressions, so head(,-1) above
     cyl gear Total
[1,]   4    0     8
[2,]   4    1     3
[3,]   6    0     4
[4,]   6    1     3
[5,]   8    1    14

在v1.8.0中添加了一个新的参数 keyby 2012)让它更简单:

A new argument keyby was added in v1.8.0 (July 2012) making it simpler :

tableOrder = function(x,.expr) {
    .expr = substitute(.expr)
    x[,list(Total=length(mpg)),keyby=.expr]
}

i j 区域的意见和反馈by 变量表达式是最受欢迎的。你可以做的另一件事是有一个表,其中列包含表达式,然后查找放在 i j 由该表中的

Comments and feedback in the area of i,j and by variable expressions are most welcome. The other thing you can do is have a table where a column contains expressions and then look up which expression to put in i, j or by from that table.

这篇关于在函数中使用data.table i和j参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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