一个简单的可复制示例,用于在R中的自定义函数中将参数传递给data.table
我已经在谷歌上搜索了几个小时这个答案。很多人问过类似的问题,但我没有找到足够简单的问题或直接的答案。我的做法如下: 假设我想在一个简单的可复制示例,用于在R中的自定义函数中将参数传递给data.table,r,function,data.table,R,Function,Data.table,我已经在谷歌上搜索了几个小时这个答案。很多人问过类似的问题,但我没有找到足够简单的问题或直接的答案。我的做法如下: 假设我想在数据中做一个简单的分组 library(data.table) mtcars = data.table(mtcars) mtcars[,sum(mpg), gear] # Here are the results # gear V1 #1: 4 294.4 #2: 3 241.6 #3: 5 106.9 但是,如果我使用自定义函数执行此操作
数据中做一个简单的分组
library(data.table)
mtcars = data.table(mtcars)
mtcars[,sum(mpg), gear]
# Here are the results
# gear V1
#1: 4 294.4
#2: 3 241.6
#3: 5 106.9
但是,如果我使用自定义函数执行此操作:
zz = function(data, var, group){
return(data[,sum(var), group])
}
zz(mtcars, mpg, gear)
我收到一条错误消息:
eval中出错(bysub,parent.frame(),parent.frame()):
找不到对象“齿轮”
我尝试过substitute
,eval
,quote
,以及其他解决方案,但没有一个有效。我想知道是否有人能给出一个更直接的解决方案和解释
谢谢你,万圣节快乐 如果我们使用的是不带引号的参数,substitute
和eval
uate
zz <- function(data, var, group){
var <- substitute(var)
group <- substitute(group)
setnames(data[, sum(eval(var)), by = group],
c(deparse(group), deparse(var)))[]
# or use
# setnames(data[, sum(eval(var)), by = c(deparse(group))], 2, deparse(var))[]
}
zz(mtcars, mpg, gear)
# gear mpg
#1: 4 294.4
#2: 3 241.6
#3: 5 106.9
zz虽然不是完美的,..
参数可能会有帮助:
zz = function(dt, ...){
return(dt[...])
}
zz(mtcars, , sum(mpg), gear)
gear V1
1: 4 294.4
2: 3 241.6
3: 5 106.9
我真的不认为编写一个接受无引号参数的函数有什么意义。为什么不直接使用data.table语法呢
如果您想编写一个函数,那么采用列名的字符向量更有意义,因为这比符号更易于编程(考虑使用setkey
与setkeyv
编程,或者使用aes
与aes\u字符串
编写函数来创建ggplot)缺点是函数的内部比较混乱,需要eval(parse(text=))NSE才能使GForce正常工作,但函数接口更具可扩展性
zz = function(data, var, group){
eval(parse(text=paste0("data[,sum(",var,"),by=",group,"]")))
}
zz(mtcars, "mpg", "gear")
@Gregor我猜它可能与env
替换(expr,env)
有关,因为替换将检查data.table的env中的变量。你可以试着改变env
,这很有意义,但是玩了一点之后,我还是无法让它工作。“我想我得问个问题……”格雷戈,我也试过了。我记得以前有过类似的问题,但没有发现。请把它当作一个问题来问。谢谢这里有一个新问题:(现在我希望我没有删除原来的评论)@Gregor谢谢你!嘿,迈克尔!这绝对是一个有趣的方法。我自己并没有写很多这样的函数,但我确实看到了无引号参数对于交互式使用的吸引力,尤其是在制表符完成时。eval parse paste仍然让我感觉很糟糕,尽管我无法识别这种情况下的任何特定风险。好吧,by
参数可以是一个带引号的字符串——可以是列名的字符向量,也可以是逗号分隔的名称的长度为一个字符的向量,但是我认为您使用.SDcols
是正确的效率较低。然而,x=c(“mpg”,“hp”)
,g=c(“am”,“cyl”)
,然后mtcars[,lappy(.SD,平均值),by=g,.SDcols=g)
写起来很好。但肯定没有允许用户输入任意字符串那么灵活。与此同时,akrun在我键入此评论时刚刚回答了…是的,.SD方法也是我尝试过的方法,几乎满足了我的任意编程标准(它在i语句中不起作用,您还需要做一些其他的技巧来获得LHS赋值中的任意列名)。最终,我反对使用.SD方法进行编程,因为它需要跟踪.SD的索引,而对于复杂的j语句,我发现很难遵循这种方法(甚至比宏更重要,宏至少可以通过评估粘贴来调试,以获得非常可读的数据。表语法)例如,单独重复地获取data.table的第1列和任意数量的其他列之间的乘积,而不使用一些挑剔的.SD索引和lappy,这可能并不简单。