2015-04-28 38 views
6

我試圖使用參數data.table子集(並將一個平均值應用於該子集)。基本上我會傳遞函數兩個鍵和第三個鍵的幾個元素;這似乎令人困惑R,但該操作完全按照預期在功能環境之外完成。功能內多個子集子集data.table令人困惑的問題

下面是一個基本上得到我想要做的事情的例子;它返回一個解決方案,是不正確,而我自己的代碼產生一個錯誤(文本粘貼以下):

set.seed(12345) 
dt<-data.table(yr=rep(2000:2005,each=20), 
       id=paste0(rep(rep(1:10,each=2),6)), 
       deg=paste0(rep(1:2,60)), 
       var=rnorm(120), 
       key=c("yr","id","deg")) 

fcn <- function(yr,ids,deg){ 
    dt[.(yr,ids,deg),mean(var)] 
} 

fcn(2004,paste0(1:3),"1") 

這給出答覆,但它是完全錯誤的(更多的在第二)。如果我這樣做手工,沒有任何問題:

> fcn(2004,paste0(1:3),"1") 
[1] 0.1262586 
> dt[yr==2004&id %in% paste0(1:3)&deg=="1",mean(var)] 
[1] 0.4374115 
> dt[.(2004,paste0(1:3),"1"),mean(var)] 
[1] 0.4374115 

要破解這是怎麼回事,我改變了fcn代碼:

fcn <- function(yr,ids,deg){ 
    dt[.(yr,ids,deg),] 
} 

其中產量:

> fcn(2004,paste0(1:3),"1") 
     yr id deg  var 
    1: 2000 1 1 0.5855288 
    2: 2000 2 2 -0.4534972 
    3: 2000 3 1 0.6058875 
    4: 2000 1 2 0.7094660 
    5: 2000 2 1 -0.1093033 
---      
116: 2005 2 2 -1.3247553 
117: 2005 3 1 0.1410843 
118: 2005 1 2 -1.1562233 
119: 2005 2 1 0.4224185 
120: 2005 3 2 -0.5360480 

基本上, fcn已完成子集化!這是爲什麼發生?真的很沮喪。

如果我只通過一個密鑰而不是三個,dt子集上的中間密鑰只有。奇怪:

> fcn(2004,"1","1") 
     yr id deg  var 
    1: 2000 1 1 0.5855288 
    2: 2000 1 2 0.7094660 
    3: 2000 1 1 0.5855288 
    4: 2000 1 2 0.7094660 
    5: 2000 1 1 0.5855288 
---      
116: 2005 1 2 -1.1562233 
117: 2005 1 1 0.2239254 
118: 2005 1 2 -1.1562233 
119: 2005 1 1 0.2239254 
120: 2005 1 2 -1.1562233 

但是如果我通過只有中間鍵的功能,它工作正常:

fcn <- function(ids){ 
    dt[.(2004,ids,"1")] 
} 
> fcn(paste0(1:3)) 
    yr id deg  var 
1: 2004 1 1 0.6453831 
2: 2004 2 1 -0.3043691 
3: 2004 3 1 0.9712207 

最後編輯:問題解決了,但它仍然會是不錯的知道是什麼究竟是走錯了:

重命名參數:

fcn <- function(yyr,ids,ddeg){ 
    dt[.(yyr,ids,ddeg),mean(var)] 
} 

有關將列名重新用作變量名的問題引發了一個問題,看起來 - 但我仍然不完全明白出了什麼問題。

+0

粉筆這是需要寫下來正確排除故障的情況。 – MichaelChirico

回答

7

的問題是你使用的列名的i-expression裏面,但希望他們是名稱data.table之外。你可以在你的函數命名的變量名,或構建之外加入data.table,然後使用一個事實,即一個名稱data.table總是會使用外部環境:

fcn <- function(yr,ids,deg){ 
    tmp = data.table(yr, ids, deg) 
    dt[tmp, mean(var)] 
} 

fcn(2004, paste0(1:3), "1") 
#[1] 0.4374115 

FAQ 2.12-2.13。

+0

所以這基本上是一個環境問題 - 我需要訪問變量'yr'和'deg',但'[.data.table'首先在'dt'的範圍內查找,並在找到那些列時停在那裏永遠不要移動到函數環境中,我傳遞給'yr'和'deg'的值被存儲。缺少任何東西? – MichaelChirico

+0

@MichaelChirico是的,這是正確的 – eddi

+0

啊,那麼爲什麼'fcn(2004,「1」,「1」)'工作是因爲只有中間參數是唯一命名的('ids'與'id')。偷偷摸摸的。 – MichaelChirico