在data.table group by子句中使用变量

时间:2015-07-24 01:21:07

标签: r list data.table

我有一个data.table,我想总结一下。这是我的方法

library(data.table)

dtIris <-data.table(iris)
dt1 <- dtIris[, list(AvgSepalWidth = mean(Sepal.Width)), 
              by=list(TrimSpecies = substr(Species,1,3),Petal.Length)]

我希望能够使用变量来识别要分组的项目之一,我只是不能让它来评估列表中的变量。它只是将它视为字符串并抛出错误。

myvar <- "Petal.Length"
dt1 <- dtIris[, list(AvgSepalWidth = mean(Sepal.Width)), 
              by=list(TrimSpecies = substr(Species,1,3),myvar)]

我尝试noquote()eval()parse(text=)都无济于事。任何指导都会非常感激。

3 个答案:

答案 0 :(得分:6)

您可以使用eval(parse(text=myvar))get(myvar),但这会分别命名您的分组列parseget(然后您可以重命名)。

myvar <- "Petal.Length"
dtIris[, list(AvgSepalWidth = mean(Sepal.Width)), 
              by=list(TrimSpecies = substr(Species,1,3), eval(parse(text=myvar)))]

dtIris[, list(AvgSepalWidth = mean(Sepal.Width)), 
              by=list(TrimSpecies = substr(Species,1,3), get(myvar))]

我不确定如何以保留名称的方式执行此操作。 (编辑:by=setNames(list(...), c('TrimSpecies', myvar)) - 谢谢@thelatemail!)

编辑 - 出于兴趣,回应下面的一些评论。

library(rbenchmark)
benchmark(
    eval=dtIris[, list(AvgSepalWidth = mean(Sepal.Width)), 
              by=list(TrimSpecies = substr(Species,1,3), eval(parse(text=myvar)))],
    get=dtIris[, list(AvgSepalWidth = mean(Sepal.Width)), 
              by=list(TrimSpecies = substr(Species,1,3), get(myvar))],
    chain=dtIris[, TrimSpecies := substr(Species,1,3)][,list(AvgSepalWidth = mean(Sepal.Width)),by=c("TrimSpecies",myvar)][,TrimSpecies:=NULL][]
)
   test replications elapsed relative user.self sys.self user.child sys.child
3 chain          100   0.151    1.987     0.250        0          0         0
1  eval          100   0.079    1.039     0.097        0          0         0
2   get          100   0.076    1.000     0.094        0          0         0

geteval(parse(text=..)))快,比定义TrimSpecies更快,使用by的字符形式然后删除它(链接dts)。

答案 1 :(得分:0)

by语句不接受字符串。它确实接受变量引用。

因此,您可以创建一个变量来复制要聚合的列的数据,而不是引用列名:

myvar <- dtIris[,Petal.Length]
dt2 <- dtIris[, list(AvgSepalWidth = mean(Sepal.Width)), 
          by=list(TrimSpecies = substr(Species,1,3),myvar)]
all(dt2==dt1)
#TRUE

答案 2 :(得分:0)

当我想要同时分组多个变量时,事情变得有点棘手。继续的方法是创建一个变量myvar,其中包含应该进行分组的列的名称(在本例中为2);然后,可以按以下方式使用get两次:

dtIris[, list(AvgSepalWidth = mean(Sepal.Width)), by = list(get(myvar[1]), get(myvar[2]))]