You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何do.call无法定位列表中存储的函数?

问题原因与解决方案

这个问题的核心在于**do.call对字符串参数的处理逻辑**,以及字符串"LM"和"model$LM"在R中的本质差异:

为什么"LM"能正常运行?

当你传入字符串"LM"给map2中的.x时,do.call(.x, ...)会把这个字符串当作函数名,在当前环境中查找同名的函数对象——而你之前已经把lm赋值给了LM,所以R能找到这个函数,自然可以正常调用。

为什么"model$LM"会报错?

而当你传入字符串"model$LM"时,do.call同样会把整个字符串当作一个完整的函数名去查找,但你的环境里根本不存在一个叫model$LM的函数(model$LM是从列表model中提取元素的表达式,不是一个函数的名字)。这就是报错提示could not find function "model$LM"的原因。

简单来说:do.call不会解析字符串形式的表达式,它只会把字符串当作单纯的对象名去查找。

解决方案

要解决这个问题,你需要先把字符串形式的表达式"model$LM"解析成对应的函数对象,再传给do.call。这里有两种常用的方式:

方式1:在map2中先解析表达式

修改mutate中res的定义,先用eval(parse(text = .x))把字符串解析成实际的函数对象:

specr:::setup_specs(y = "y", x = "x", model = "model$LM" ) %>% 
dplyr::mutate(formula = pmap(., specr:::create_formula) ) %>% 
tidyr::unnest(formula) %>% 
dplyr::mutate(res = map2(.data$model, formula, ~do.call(eval(parse(text = .x)), list(data = df, formula = .y))))

注意:parse(text = ...)虽然能解决问题,但如果字符串来自不可信来源,可能存在安全风险,不过在你的调试场景中是完全可行的。

方式2:提前提取函数对象,避免传入复杂字符串

更稳妥的方式是,不要给setup_specs传入字符串"model$LM",而是直接传入函数对象本身:

# 直接传入函数对象
specr:::setup_specs(y = "y", x = "x", model = list(model$LM) ) %>% 
dplyr::mutate(formula = pmap(., specr:::create_formula) ) %>% 
tidyr::unnest(formula) %>% 
dplyr::mutate(res = map2(.data$model, formula, ~do.call(.x, list(data = df, formula = .y))))

这种方式跳过了字符串解析的步骤,直接传递函数对象,更安全也更高效。

内容的提问来源于stack exchange,提问作者GiulioGCantone

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.27 18:22:47