2010-07-15 56 views
7

我想使用R中的data.table包动态生成聚合,但我遇到了一个错误。下面,让my.dtdata.table类型。data.table和“必须评估列表”错误

sex <- c("M","F","M","F") 
age <- c(19, 23, 26, 21) 
dependent.variable <- c(1400, 1500, 1250, 1100) 
my.dt <- data.table(sex, age, dependent.variable) 
grouping.vars <- c("sex", "age") 
for (i in 1:2) { 
    my.dt[,sum(dependent.variable), by=grouping.vars[i]] 
} 

如果我跑,我得到的错误:

Error in `[.data.table`(my.dt, , sum(dependent.variable), by = grouping.vars[i] : 
    by must evaluate to list 

然而,以下的作品没有错误:

my.dt[,sum(dependent.variable), by=sex] 

我明白为什么错误发生,但我没有看到如何使用带有by参数的矢量。

+0

你有两个“grouping.vars”,但是从1:5迭代。我在那里错过了什么? – Shane 2010-07-15 02:41:39

+1

另外,在你的工作例子中,性是一个对象,而在你失败的版本中,它是一个角色。 – Shane 2010-07-15 02:49:24

+0

嘿谢恩,对不起,修好了。应该是2不是5.那是我不清楚的,看来性是一个对象(??)。 – 2010-07-15 03:08:20

回答

4

我做了两处更改原密码:

sex <- c("M","F","M","F") 
age <- c(19, 23, 26, 21) 

age<-as.factor(age) 

dependent.variable <- c(1400, 1500, 1250, 1100) 
my.dt <- data.table(sex, age, dependent.variable) 

for (a in 1:2){ 
print(my.dt[,sum(dependent.variable), by=list(sex,age)[a]]) 
} 

数值矢量age应该被迫的因素。至于by参数,不要对列名使用引号,而将它们分组到列表(...)中。至少这是作者所建议的。

+0

这很有趣,“by”背后的设计看起来有点反意思,但是你的代码大部分工作。 只有一个小问题(小而易于通过在循环中分配名称来修复),列名不会更新。 对于可变性,姓名是:性别V1 对于可变年龄,姓名是:性别V1 – 2010-07-15 04:54:57

5

[更新】2年后,问题有人问...

在运行中的问题的代码,data.table现在更乐于助人,回报这个(使用1.8.2):

Error in `[.data.table`(my.dt, , sum(dependent.variable), by = grouping.vars[i]) : 
    'by' appears to evaluate to column names but isn't c() or key(). Use by=list(...) 
    if you can. Otherwise, by=eval(grouping.vars[i]) should work. This is for efficiency 
    so data.table can detect which columns are needed. 

并按照错误的第二句忠告:

my.dt[,sum(dependent.variable), by=eval(grouping.vars[i])] 
    sex V1 
1: M 2650 
2: F 2600 


从2010年7月

老答案(by现在可以doublecharacter,虽然):

严格地说by需求评估与存储模式整数时,每个向量的名单,虽然。所以数字矢量age也可以使用as.integer()强制为整数。这是因为data.table使用基数排序(非常快),但基数算法专门用于整数只有(请参阅维基百科的'基数排序'条目)。整数存储键列和特设by是data.table速度快的原因之一。一个因素当然是对唯一字符串的整数查找。

by是表达式的list()背后的想法是,您不限于列名。通常在by中直接编写表达式的列表名称。常见的是按月汇总;例如:

DT[,sum(col1), by=list(region,month(datecol))] 

或通过yearmonth一个非常快速的方式来组是通过使用非划时代基于日期,如yyyymmddL在一些包中的例子看到的,这样的:

DT[,sum(col1), by=list(region,month=datecol%/%100L)] 

请注意,您可以像这样命名列表()中的列。

定义和重用复杂的分组表达式:

e = quote(list(region,month(datecol))) 
DT[,sum(col1),by=eval(e)] 
DT[,sum(col2*col3/col4),by=eval(e)] 

或者,如果你不想每次都重新评估by表达式,可以一次保存的结果和重用效率的结果;如果by表达式本身需要很长的时间来计算/分配,或者你需要重复使用很多次:

byval = DT[,list(region,month(datecol))] 
DT[,sum(col1),by=byval] 
DT[,sum(col2*col3/col4),by=byval] 

请参阅http://datatable.r-forge.r-project.org/得到最新的信息和状态。一个新的演示文稿将很快出现在那里,并希望很快将1.5版发布到CRAN。这包含在NEWS文件中详细说明的几个错误修复和新功能。数据表帮助列表每月大约有30-40个帖子,这也许是有趣的。