使用apollo选择建模包动态指定函数的技术咨询
问题
使用选择建模包apollo时,需要在循环迭代中动态生成模型输入函数,要求:
- 不能修改函数的参数列表
- 函数内部使用
attach - 每次循环修改函数中
V[["first"]]的赋值表达式,排除指定的变量项(例如第一次排除Age相关项,第二次排除Female相关项)
尝试的代码无法实现需求,因为函数内部的x只是引用外部变量,而非将解析后的表达式直接写入函数体:
for(var in c("Age", "Female")) { x <- parse(text = c("delta_a","gamma_Age_a*Age","gamma_Female_a*Female") %>% str_subset(var, negate = TRUE) %>% paste(collapse = "+")) assign("dynamic_fun", function(args){ x }) }
原函数结构如下,需要修改其中V[["first"]]的赋值内容:
existing_fun <- function(args){ # 其他固定代码... V=list() V[["first"]] = delta_a + gamma_Age_a*Age + gamma_Female_a*Female # 其他固定代码... }
期望循环生成两个不同的函数,分别对应排除Age或Female的表达式:
# 排除Age的函数 fun <- function(args){ # 其他固定代码... V=list() V[["first"]] = delta_a + gamma_Female_a*Female # 其他固定代码... } # 排除Female的函数 fun <- function(args){ # 其他固定代码... V=list() V[["first"]] = delta_a + gamma_Age_a*Age # 其他固定代码... }
解决方案
核心思路是直接修改函数的表达式体,将动态生成的表达式硬编码到函数内部,而非依赖闭包引用外部变量。具体实现如下:
# 1. 定义原函数模板 existing_fun <- function(args){ # 这里保留所有固定不变的代码 cat("执行固定代码...\n") V = list() V[["first"]] = delta_a + gamma_Age_a*Age + gamma_Female_a*Female # 其他固定代码... return(V) } # 2. 循环处理每个需要排除的变量 for(var in c("Age", "Female")){ # 生成要保留的表达式项 all_terms <- c("delta_a", "gamma_Age_a*Age", "gamma_Female_a*Female") keep_terms <- all_terms[!grepl(var, all_terms)] target_expr <- parse(text = paste(keep_terms, collapse = "+"))[[1]] # 复制原函数并修改其表达式体 new_fun <- existing_fun fun_body <- body(new_fun) # 定位到V[["first"]]的赋值行(根据实际函数结构调整索引或匹配规则) assign_index <- which(sapply(fun_body, function(line) { grepl("V\\[\\[\"first\"\\]", deparse(line)) })) # 替换赋值表达式 fun_body[[assign_index]] <- substitute(V[["first"]] = EXPR, list(EXPR = target_expr)) body(new_fun) <- fun_body # 验证结果(此处可将new_fun传入apollo模型) cat("\n生成的函数体(排除", var, "):\n") print(body(new_fun)) }
关键说明
- 用
body()获取函数的表达式体(语言对象),直接修改其中的赋值语句,避免闭包变量的引用问题 - 通过
parse()将字符串转为表达式,再用substitute()替换到函数体中,确保每次生成的函数内部包含独立的硬编码表达式 - 循环中每次复制原函数模板,修改后得到新的函数,满足apollo对输入函数的要求
内容的提问来源于stack exchange,提问作者jayb
相关产品推荐
相关产品推荐

