2013-11-21 42 views
1

问题1:为什么它不一致?data.table by替代,eval和deparse

dt <- data.table(x=1:4, y=c(1,1,2,2), z=c(1,2,1,2)) 

test1 <- function(dt, a){ 
    t <- deparse(substitute(a)) 
    dt[,list(x=sum(x)), by=t] 

} 
test1(dt, y) # Works well 
    y x 
1: 1 3 
2: 2 7 

test2 <- function(dt, a){ 
    dt[,list(x=sum(x)), by=deparse(substitute(a))] 
} 
test2(dt, y) 
# Error: 'by' appears to evaluate to column names but isn't c() or key(). 

问题2:

看来我可以做两个框架下?这是为什么?我应该使用哪一个?

test1 <- function(dt, a){ 
    dt[,list(x=sum(x)), by=eval(substitute(a))] 

} 
test1(dt, y) 
    substitute x 
1:   1 3 
2:   2 7 
> 
test2 <- function(dt, a){ 
    dt[,list(x=sum(x)), by=eval(substitute(a), parent.frame())]  
} 
test2(dt, y) 
    substitute x 
1:   1 3 
2:   2 7 
+3

对于(1),我认为错误信息非常清晰(您只粘贴了信息的前半部分)。剩下的就是:“如果可以,使用'by = list(...)'否则,'by = eval(deparse(substitute(y)))'应该起作用。可以检测到需要哪些列“。 (2)看看''eval'(正如我在你的其他文章中回答的那样)。 – Arun

+0

@Arun使用不同的框架评估默认显式参数https://stat.ethz.ch/pipermail/r-help/2010-February/227582.html – colinfang

回答

1

你没有重现完整的错误:

test2(dt, y) Error in [.data.table (dt, , list(x = sum(x)), by = deparse(substitute(a))) : 'by' appears to evaluate to column names but isn't c() or key(). Use by=list(...) if you can. Otherwise, by=eval(deparse(substitute(a))) should work. This is for efficiency so data.table can detect which columns are needed.

至于建议(或者仅仅是在暗示),你可以通过刚刚在c

test2 <- function(dt, a){ 
    dt[,list(x=sum(x)), by=c(deparse(substitute(a)))] 
    } 

> test2(dt, y) 
    y x 
1: 1 3 
2: 2 7 

我认为封闭获得成功c()强制进行评估。

+0

+1。它也在下一句中提供了一个可供选择的答案。 – Arun

+0

因为'eval(deparse(substitute()))是一点点巴洛克式的,所以我认为使用'c(。)'的​​成功是值得一提的,用'list(。)'成功' –

+0

完全。我实际上是指下一句“eval(。)”。 'deparse(替代(。))'是一个相对罕见/不常见的情况。目标是捕捉常见的情况。但也许这也可以检查。将提交一个FR以防万一,并链接回去。再次感谢您重振这篇文章! – Arun