我正在尝试使用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)°=="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)
关于重新使用列名作为变量名称的问题似乎引起了一个问题 - 但我仍然没有完全理解出了什么问题.
问题是你正在使用你的内部列的名称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.