r - 如何在 R 中获得 lm() 和 nls() 求解器以自洽地处理具有偏移的线性公式?
问题描述
我有一些与线性模型一致的时间序列数据( x,y )。我想构建一个回归公式,其中一个系数对应于特定时刻(例如,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()
,那么这些规则在哪里写下来,以便我下次可以避免与它们发生冲突?
解决方案
推荐阅读
- angular - Compodoc 可以生成降价文档,而不是其默认的 HTML 文档吗?
- javascript - 如何向此代码添加特定时区?
- ruby-on-rails - ActiveRecord 何时运行查询?
- angular - 如何在 mat-select 中显示选定的图像
- python - 如何在 Jira 中获取自定义字段的选项?
- ios - 致命错误 Xcode 9.4 beta - 全红无法访问文件
- aes - C中的AES GCM机制参数
- css - 在静态定位正常布局中,body元素的高度是否默认不是其容器的100%?
- java - 邮递员测试
- javascript - Chrome 浏览器扩展的 Google Analytics 事件未触发