首页 > 解决方案 > 如何在 R 中获得 lm() 和 nls() 求解器以自洽地处理具有偏移的线性公式?

问题描述

我有一些与线性模型一致的时间序列数据( xy )。我想构建一个回归公式,其中一个系数对应于特定时刻(例如,2013 年 1 月 1 日)的y值,而不是x = 0处的y截距(这将对应到公元 0 年 1 月 1 日,迄今为止不感兴趣)。

使用nls(), 求解器,我能够构建我想要的模型类型,并使用模拟的测试数据,我能够从中得到合理的结果(这意味着拟合结果近似地再现了我使用的“真实”值生成人工样本数据)。使用lm()求解器,我还能够构建一个线性模型,但是它默认为我提供一个我不想要的时间值的拟合y截距;即,公元 0 年 1 月 1 日,当我尝试为求解器提供与lm()求解器相同的公式时nls(),它返回一个invalid model formula错误:

# Force warnings to be printed as they are generated
options(warn=1)

# -------------------
# Define Linear Model
# -------------------

# Express the same linear model three ways:
#   1.) As a function (needed for constructing test data)
#   2.) As a formula appropriate for nls()
#   3.) As a formula appropriate for lm() [has 2013 offset removed]
# In first two versions, physical interpretations of model coefficients are:
#   sv:    starting value on Jan 1, 2013
#   slope: annual rate of linear increase
linear_func <- function(year, sv, slope) {
  sv + slope * (year-2013)
}
linear_form_offset <- (value ~ sv + slope * (year-2013))
linear_form_nooffset <- (value ~ year)

# -------------------
# Construct Test Data
# -------------------

sv_true <- 5000
slope_true <- 1500
year <- c(2013.5, 2014.5, 2015.5, 2016.5, 2017.5, 2018.5, 2019.5)
# Use truth values, and add some Gaussian noise
value <- linear_func(year, sv_true, slope_true) + rnorm(length(year), sd=100)
dftest <- data.frame(year, value)

# ------------------
# Obtain Fit Results
# ------------------

# nls solver requires approximate starting values, somewhere near the local
# vicinity of the final optimized values.
print("Now running nls (with offset)")
initcoef <- c(sv=3000, slope=1000)
fitresult <-  nls(formula=linear_form_offset, data=dftest, start=initcoef)
print(coef(fitresult))

# lm solver, by contrast, has no concept of starting values, so omit them here
print("Now running lm (no offset)")
fitresult <- lm(formula=linear_form_nooffset, data=dftest)
print(coef(fitresult))

# lm solver using the offset formula that I would actually like to use --
# this results in an invalid model formula error.
print("Now running lm (with offset)")
fitresult <- lm(formula=linear_form_offset, data=dftest)
print(coef(fitresult))

当我运行这个示例时,我得到以下典型结果:

source("test_fit.R")
[1] "Now running nls (with offset)"
      sv    slope 
5002.463 1518.854 
[1] "Now running lm (no offset)"
 (Intercept)         year 
-3052450.171     1518.854 
[1] "Now running lm (with offset)"
Error in terms.formula(formula, data = data) : 
  invalid model formula in ExtractVars
>

问题 1(简单):我知道,给定公元 0 年 1 月 1 日的y截距和斜率,我可以轻松计算 2013 年 1 月 1 日的相应y值。但是,由于各种原因,我不希望要做到这一点。我只想构建我真正想要的实际回归模型,并使用lm(). 有什么方法(例如,首选的替代语法)可以做到这一点吗?

问题 2(更深层次):这里到底发生了什么?我对公式的天真理解是,它们是 R 中的一种特定对象类型——一个公式应该独立地作为一种内在有效或无效的结构,而不需要外部参考试图回归它的求解器算法。但是这里公式的有效性似乎完全取决于哪个求解器实际使用它。为什么是这样?如果构建有效公式的规则lm()与 vs.不同nls(),那么这些规则在哪里写下来,以便我下次可以避免与它们发生冲突?

标签: rformulalmnls

解决方案


推荐阅读