在函数中使用data.table i和j参数 - 代码日志

在函数中使用data.table i和j参数

我正在尝试编写一些包装函数,以减少与data.table的代码重复。

这是使用mtcars的一个例子。首先,设置一些数据:

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

现在,这里是我通常写的,以得到一个按组的计数的总结。在这种情况下,我正在分车:

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(…),如果要传入变量:

这样做:

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

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

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

我知道为什么:这是因为组是在parent.frame中评估的,而不是data.table的框架。

如何在data.table的上下文中评估组?

更一般地说,如何在函数中使用这个?我需要以下功能给我所有的结果,而不仅仅是第一行数据:

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

tableOrder(mtcars, "car")
加文和乔希是对的。这个答案只是增加了更多的背景。这个想法是,您不仅可以将变量列名称传递给类似的函数,还可以使用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(),像这样:

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(2012年7月)中增加了一个新的参数keyby,使其更简单:

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

对i,j和变量表达式的评论和反馈是非常受欢迎的。您可以做的另一件事就是有一个表,其中列包含表达式,然后查找要放入i,j或从该表中的表达式。

http://stackoverflow.com/questions/9705488/using-data-table-i-and-j-arguments-in-functions

本站文章除注明转载外,均为本站原创或编译
转载请明显位置注明出处:在函数中使用data.table i和j参数