使用optim进行带约束线性回归时遇‘closure不可子集化’错误求助
问题分析与修正方案
首先,咱们来拆解你遇到的Error in par[1] : object of type 'closure' is not subsettable错误,以及代码里的其他问题:
错误根源
par变量未定义,触发内置函数冲突
你在测试min.RSS(par, data=df, form=formula)时,par这个变量根本没赋值。而R有个内置的par()函数(用来设置图形参数),所以R把你写的par当成了这个内置函数——函数属于closure类型,不能用[1]做子集操作,自然报错。optim参数传递完全错误optim的第二个参数需要传入目标函数本身,而不是函数的调用结果。你现在写的min.RSS(par, data=df, form=formula)是直接执行函数,这完全不符合optim的语法要求。动态生成的公式语法混乱
你的formfun生成的表达式有多余的括号、逗号,比如sum(()par[1] * df[2] + ,...),这种语法错误会导致eval(parse(...))无法正确计算RSS。目标函数依赖全局变量
min.RSS里直接用了全局的df,而不是传入的data参数,这不仅让函数失去复用性,还容易引发变量作用域问题。
修正后的完整代码
set.seed(1000) # 修正:生成因变量+n个自变量的数据框,循环逻辑更清晰 sampler <- function(n){ df <- data.frame(y = sample(-100:100, 5000, replace = TRUE)) # 循环生成n个自变量列,从第2列开始 for (i in 1:n){ df[, i+1] <- sample(-100:100, 5000, replace = TRUE) } # 给自变量列命名,方便后续查看 colnames(df)[-1] <- paste0("x", 1:n) df } # 修正:生成正确的RSS计算公式字符串 formfun <- function(n) { # 生成每个自变量的项:par[i] * data[,i+1] terms <- sapply(1:n, function(i) paste0("par[", i, "] * data[,", i+1, "]")) # 把所有项用+连接成线性预测表达式 linear_pred <- paste(terms, collapse = " + ") # 组合成完整的RSS计算式:sum((线性预测值 - y)^2) paste0("sum( (", linear_pred, " - data[,1])^2 )") } # 修正:使用传入的data参数,不再依赖全局变量 min.RSS <- function(par, data, form) { eval(parse(text = form)) } # 测试代码 n <- 5 df <- sampler(n) formula <- formfun(n) # 修正:optim的参数传递逻辑 result <- optim( par = rep(1, n), # 初始参数值 fn = min.RSS, # 目标函数本身 data = df, # 传递给min.RSS的额外参数 form = formula, method = "L-BFGS-B", # 带边界约束的优化方法 lower = rep(0, n), # 每个系数的下界:非负 upper = rep(10000, n) # 每个系数的上界 ) # 查看结果 result$par # 约束后的系数 result$value # 最小化的RSS
关键修正说明
sampler函数:调整了循环逻辑,给自变量列命名,让数据结构更清晰。formfun函数:生成语法正确的RSS表达式,避免了多余的符号,同时使用data参数而不是全局df。min.RSS函数:严格使用传入的data参数,消除全局变量依赖。optim调用:正确传递目标函数min.RSS,并通过额外参数传递data和form;lower设置为长度为n的0向量,确保每个系数都满足非负约束。
内容的提问来源于stack exchange,提问作者Jan Felix
相关产品推荐
相关产品推荐

