在函数内的多键子集化data.table上混淆问题

时间:2015-04-28 21:20:19

标签: r data.table

我正在尝试将data.table的参数用于子集(并对该子集应用均值)。基本上我将传递给函数的两个键和第三个键的几个元素;这似乎让人感到困惑R,但是当在函数环境之外完成时,操作完全符合预期。

这是一个基本上得到我想要做的事情的例子;它返回一个不正确的解决方案,而我自己的代码产生错误(下面粘贴的文本):

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)]
}

关于重新使用列名作为变量名称的问题似乎引起了一个问题 - 但我仍然没有完全理解出了什么问题。

1 个答案:

答案 0 :(得分: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。