R中data.table cube()自定义函数报‘object not found’错误的解决咨询
解决data.table cube()函数封装时的"object not found"错误
问题重现
使用R 4.2.1与data.table 1.14.2版本时,直接调用cube()可以正常运行,但将其封装到自定义函数后出现object not found错误:
library(data.table) f <- function(values, dec_places) { round(sum(values), digits = dec_places) } DT <- data.table(x = c("a", "a", "b", "b"), y = c(1.101, 1, 2.101, 1)) x_var <- "x" y_var <- "y" dp <- 1 # 直接调用正常运行 cube(DT, f(get(y_var), dec_places = dp), by = x_var) # x V1 # 1: a 2.1 # 2: b 3.1 # 3: <NA> 5.2 # 封装为函数后报错 g <- function(Data, num_var, group_var, decimal_places) { cube(Data, f(get(num_var), dec_places = decimal_places), by = group_var) } g(Data = DT, num_var = y_var, group_var = x_var, decimal_places = dp) # Error in get(num_var) : object 'num_var' not found
错误原因
这是作用域解析问题:
cube()执行传入的表达式时,默认会在传入的Data对象的环境(即data.table自身的列环境)中查找变量- 自定义函数
g中的num_var是函数的局部变量,并不存在于Data的环境中,因此get(num_var)无法找到该对象,触发报错
解决方法
方法1:使用.SDcols指定目标列
利用data.table的.SD(Subset of Data)和.SDcols参数,直接从分组后的子集中提取目标列,无需依赖get():
g <- function(Data, num_var, group_var, decimal_places) { cube(Data, f(.SD[[1]], dec_places = decimal_places), by = group_var, .SDcols = num_var) } # 测试运行 g(Data = DT, num_var = y_var, group_var = x_var, decimal_places = dp) # x V1 # 1: a 2.1 # 2: b 3.1 # 3: <NA> 5.2
方法2:构造并求值表达式
通过substitute()将函数局部变量替换到表达式中,再用eval()执行,确保cube()能正确解析变量:
g <- function(Data, num_var, group_var, decimal_places) { # 构造包含实际变量值的表达式 calc_expr <- substitute(f(get(nv), dec_places = dp), list(nv = num_var, dp = decimal_places)) cube(Data, eval(calc_expr), by = group_var) } # 测试运行 g(Data = DT, num_var = y_var, group_var = x_var, decimal_places = dp) # x V1 # 1: a 2.1 # 2: b 3.1 # 3: <NA> 5.2
方法3:显式指定get()的查找环境
在get()中通过envir参数指定从当前函数环境中查找变量,明确作用域:
g <- function(Data, num_var, group_var, decimal_places) { cube(Data, f(get(num_var, envir = environment()), dec_places = decimal_places), by = group_var) } # 测试运行 g(Data = DT, num_var = y_var, group_var = x_var, decimal_places = dp) # x V1 # 1: a 2.1 # 2: b 3.1 # 3: <NA> 5.2
内容的提问来源于stack exchange,提问作者mark999
相关产品推荐
相关产品推荐

