2015-04-28 35 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