在 data.table group by 子句中使用变量
Using variable in data.table group by clause
我有一个 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=)
都没有用。任何指导将不胜感激。
您可以使用 eval(parse(text=myvar))
或 get(myvar)
,尽管这将分别命名您的分组列 parse
或 get
(然后您可以重命名)。
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
get
比 eval(parse(text=..)))
快,后者比定义 TrimSpecies
快,使用 by
的字符形式然后删除它(链接 dts)。
by
语句不接受字符串。它确实接受变量引用。
因此,您可以创建一个变量来复制要聚合的列的数据,而不是引用列名:
myvar <- dtIris[,Petal.Length]
dt2 <- dtIris[, list(AvgSepalWidth = mean(Sepal.Width)),
by=list(TrimSpecies = substr(Species,1,3),myvar)]
all(dt2==dt1)
#TRUE
当我想同时按 1 个以上的变量分组时,事情变得有点棘手。继续的方法是创建一个变量 myvar
,其中包含应该根据其进行分组的列的名称(在本例中为 2);然后可以按以下方式使用 get
两次:
dtIris[, list(AvgSepalWidth = mean(Sepal.Width)), by = list(get(myvar[1]), get(myvar[2]))]
我有一个 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=)
都没有用。任何指导将不胜感激。
您可以使用 eval(parse(text=myvar))
或 get(myvar)
,尽管这将分别命名您的分组列 parse
或 get
(然后您可以重命名)。
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
get
比 eval(parse(text=..)))
快,后者比定义 TrimSpecies
快,使用 by
的字符形式然后删除它(链接 dts)。
by
语句不接受字符串。它确实接受变量引用。
因此,您可以创建一个变量来复制要聚合的列的数据,而不是引用列名:
myvar <- dtIris[,Petal.Length]
dt2 <- dtIris[, list(AvgSepalWidth = mean(Sepal.Width)),
by=list(TrimSpecies = substr(Species,1,3),myvar)]
all(dt2==dt1)
#TRUE
当我想同时按 1 个以上的变量分组时,事情变得有点棘手。继续的方法是创建一个变量 myvar
,其中包含应该根据其进行分组的列的名称(在本例中为 2);然后可以按以下方式使用 get
两次:
dtIris[, list(AvgSepalWidth = mean(Sepal.Width)), by = list(get(myvar[1]), get(myvar[2]))]