2010-07-15 93 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個帖子,這也許是有趣的。