r - 在函数工厂创建的函数中调用 lm 时出现“找不到对象”
问题描述
我正在尝试建立一个通用框架来快速评估各种模型。我正在尝试使用工厂模式来生成“模型训练器”函数,这些函数采用数据框并返回经过训练的模型。lm
但是,我在这个框架中遇到了 R 的内置函数的意外行为。
gen_lm_model_trainer <- function(formula, weights_col = NULL) {
function(train_data) {
trained_lm <- lm(formula = formula,
data = train_data,
weights = train_data[[weights_col]])
pred_func <- function(test_data) {
prediction <- predict(trained_lm, newdata = test_data)
return(prediction)
}
return(list(predict = pred_func, info = trained_lm))
}
}
mtcars$random_weights <- rbeta(nrow(mtcars), shape1 = 5, shape2 = 2)
trainer <- gen_lm_model_trainer(formula = mpg ~ ., weights_col = 'random_weights')
trained_model <- trainer(mtcars)
对此代码的响应如下:
Error in eval(extras, data, env) : object 'train_data' not found
这与另一个 SO 问题类似,Object not found error when passing model formula to another function,但是通过将公式的环境分配给生成的函数的环境并不能解决这个问题,即
gen_lm_model_trainer <- function(formula, weights_col = NULL) {
function(train_data) {
scoped_formula <- as.formula(formula, env = environment())
trained_lm <- lm(formula = scoped_formula,
data = train_data,
weights = train_data[[weights_col]])
pred_func <- function(test_data) {
prediction <- predict(trained_lm, newdata = test_data)
return(prediction)
}
return(list(predict = pred_func, info = trained_lm))
}
}
一个对这两个问题都有效的解决方案将不胜感激。
解决方案
我找到了对这个问题的部分答案——部分是因为它只解决了这种情况,而不是链接的 SO 问题。问题似乎是 lm 的参数正在与调用对应的环境中进行评估with(train_data, lm(...))
。parent.frame()
因此,使用它来遍历调用函数(“模型训练器”)的环境应该是安全的。这恰好对应于 n = 1 的深度——在这种情况下,我认为 n = 1 是数据框的环境,n = 2 是 eval 的环境,n = 3 是从中lm
调用的环境。
gen_lm_model_trainer <- function(formula, weights_col = NULL) {
function(train_data) {
trained_lm <- lm(formula = formula,
data = train_data,
weights = get('train_data', parent.frame(3))[[get('weights_col', parent.frame(3))]])
pred_func <- function(test_data) {
prediction <- predict(trained_lm, newdata = test_data)
return(prediction)
}
return(list(predict = pred_func, info = trained_lm))
}
}
mtcars$random_weights <- rbeta(nrow(mtcars), shape1 = 5, shape2 = 2)
trainer <- gen_lm_model_trainer(formula = mpg ~ ., weights_col = 'random_weights')
trained_model <- trainer(mtcars)
我不清楚为什么lm
如此不寻常地更改范围,并且似乎是一个错误。
推荐阅读
- sql - 试图弄清楚为什么这个 SQL 请求需要 47 分钟才能执行
- c# - 暴露继承的事件
- mysql - 每个组件有多少构成总计数
- android - 有没有办法从 json url 获取数据
- c - 排序在 main() 中工作,但不在单独的函数中
- javascript - 如何用数据更新 v-if?
- python - 无法获得用于计算迭代次数的 Python 函数以正常工作
- javascript - 如何将链接指向加载到另一个页面上的 iframe 中的页面,并通过单击将其滚动到位置?
- java - Spring - 如何使用 SAML 2.0 实现单点登录
- python - 图例颜色不匹配绘图颜色