【发布时间】:2020-02-20 15:48:43
【问题描述】:
拥有一个lm 对象,我需要根据其表示为字符向量的变量创建一个函数。我尝试使用eval 和expr 的组合来创建f 函数,该函数将进一步用于obj 和nlm 后者的优化。
library(tidyverse)
df <- drop_na(airquality)
model <- lm(Ozone~. - Temp, data = df, x=TRUE, y=TRUE)
base_vars <- all.vars(formula(model)[-2])
k <- length(base_vars)
f <- function(base_df, x, y, parms) {
with(base_df, parms[1] +
eval(expr(paste(paste(paste0('parms[', 2:(k+1), ']'), base_vars, sep = '*'), collapse = '+'))) +
log(parms[k+2] * (x - parms[k+3] ^ 2)))
}
obj <- function(parms, y, x) mean((residuals(model) - f(df, x, y, parms))^2)
fit <- with(data, nlm(obj, c(0, 0, 0, 0, 0, 0, 0), y = e, x = x))
但是调用f(model$x, df$Temp, model$y, c(0, 0, 0, 0, 0, 0, 0))会导致以下错误:
Error in eval(substitute(expr), data, enclos = parent.frame()) :
numeric 'envir' arg not of length one
4.
eval(substitute(expr), data, enclos = parent.frame())
3.
with.default(base_df, parms[1] + eval(expr(paste(paste(paste0("parms[",
2:(k + 1), "]"), base_vars, sep = "*"), collapse = "+"))) +
log(parms[k + 2] * (x - parms[k + 3]^2)))
2.
with(base_df, parms[1] + eval(expr(paste(paste(paste0("parms[",
2:(k + 1), "]"), base_vars, sep = "*"), collapse = "+"))) +
log(parms[k + 2] * (x - parms[k + 3]^2)))
1.
f(model$x, df$Temp, model$y, c(0, 0, 0, 0, 0, 0, 0))
我相信eval 环境和with 函数所隐含的环境之间可能存在冲突,但不知道为什么。任何想法如何为变量模型创建自定义函数f?
f(model$x, df$Temp, model$y, c(0, 0, 0, 0, 0, 0, 0)) 的预期输出为:
with(base_df, parms[1]+parms[2]*Solar.R+parms[3]*Wind+parms[4]*Temp+parms[5]*Month+
parms[6]*Day+log(parms[7] * (Temp - parms[8] ^ 2)))
但对于不同的模型,它可能是这样的:
with(base_df,
parms[1]+parms[2]*var1+parms[3]*var2+log(parms[4]*(var3-parms[5]^2)))
所以每次调用的变量和参数的数量都是不同的。
【问题讨论】:
-
你能用文字描述一下你想要这个
f函数做什么吗?可能有比打扰eval更好的方法 -
我完全不知道你的函数应该在那里返回什么。公式对象?公式应该是怎样的?
-
f 函数应该创建一个具有线性部分(使用
model变量)和非线性部分log(A * (x-B))的函数。需要该函数来促进应该在nlm优化中使用的obj函数。 (我已经相应地编辑了代码) -
我还是不明白。你能写出线性部分的公式吗?我怀疑我可以提供一个简单的解决方案,但您复杂的代码尝试没有提供明确的要求。
-
我已经更新了预期的输出。请看上面的帖子。
标签: r environment-variables non-standard-evaluation