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

Mic*_*ico 6 r data.table

我正在尝试使用a 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")
Run Code Online (Sandbox Code Playgroud)

这是一个答案,但这是完全错误的(在一秒钟内更多).如果我手工完成,没有问题:

> 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
Run Code Online (Sandbox Code Playgroud)

要破解正在发生的事情,我将fcn代码更改为:

fcn <- function(yr,ids,deg){
  dt[.(yr,ids,deg),]
}
Run Code Online (Sandbox Code Playgroud)

产量:

> 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
Run Code Online (Sandbox Code Playgroud)

基本上,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
Run Code Online (Sandbox Code Playgroud)

但是,如果我只将中间键传递给函数,它可以正常工作:

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
Run Code Online (Sandbox Code Playgroud)

最终编辑:问题解决了,但知道到底出了什么问题仍然很好:

重命名参数:

fcn <- function(yyr,ids,ddeg){
  dt[.(yyr,ids,ddeg),mean(var)]
}
Run Code Online (Sandbox Code Playgroud)

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

edd*_*ddi 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
Run Code Online (Sandbox Code Playgroud)

见FAQ 2.12-2.13.

  • @MichaelChirico尝试`dt [.(yr),allow = T]`vs`dt [.(unique(yr))]`来看看差异 (3认同)