关于R data.table cube()函数作用域的困惑及传参问题
data.table::cube() 作用域问题与函数传递解决方案
问题原因
data.table的cube()、rollup()、groupingsets()这类函数在解析j参数中的表达式时,默认会在目标数据对象的内部环境中查找符号,而非调用cube()的函数环境。
第一个示例能运行,是因为summary_fn定义在全局环境中,而全局环境是数据对象环境的父环境,因此可以被找到;但第二个示例中,summary_fn是cube_fn的局部参数,仅存在于cube_fn的函数环境中,数据对象的环境无法访问这个局部作用域,所以会抛出could not find function "summary_fn"的错误。
正确传递函数的方法
方法1:使用get()指定环境获取函数
通过get()从cube_fn的父环境(即函数本身的环境)中提取summary_fn:
cube_fn = function(summary_fn) { cubed <- data.table::cube( flights, .(distance = get("summary_fn", parent.frame())(distance)), by = c("month", "origin") ) } print(cube_fn(mean))
方法2:结合eval()与quote()控制表达式求值环境
先将j表达式用quote()包裹,再通过eval()指定在cube_fn的环境中求值:
cube_fn = function(summary_fn) { j_expr <- quote(.(distance = summary_fn(distance))) cubed <- data.table::cube( flights, eval(j_expr, envir = environment()), by = c("month", "origin") ) } print(cube_fn(mean))
方法3:使用rlang的非标准求值(!!)
借助rlang包的!!操作符,将局部函数参数直接注入表达式中:
library(rlang) cube_fn = function(summary_fn) { cubed <- data.table::cube( flights, .(distance = !!summary_fn(distance)), by = c("month", "origin") ) } print(cube_fn(mean))
内容的提问来源于stack exchange,提问作者Matt
相关产品推荐
相关产品推荐

