在R中使用nls重新创建研究
我正在学习如何在R中使用nls函数,我遇到了一些问题。我现在只是试图重现一篇研究论文中发现的曲线。该模型拟合了1987年崩盘前的股市走势曲线 我定义了一个函数func,如下所示:在R中使用nls重新创建研究,r,nls,R,Nls,我正在学习如何在R中使用nls函数,我遇到了一些问题。我现在只是试图重现一篇研究论文中发现的曲线。该模型拟合了1987年崩盘前的股市走势曲线 我定义了一个函数func,如下所示: func <- function(a,b,tc,t){ a+b*log(tc-t) } 我在运行nls时收到以下消息 Error in qr(.swts * attr(rhs, "gradient")) : dims [product 4] do not match the length of obje
func <- function(a,b,tc,t){
a+b*log(tc-t)
}
我在运行nls时收到以下消息
Error in qr(.swts * attr(rhs, "gradient")) :
dims [product 4] do not match the length of object [1466]
In addition: Warning message:
In .swts * attr(rhs, "gradient") :
longer object length is not a multiple of shorter object length
据我所知,数据框的设置方式存在问题,但我无法找到解决方案
你知道我怎样才能让这位父亲走下去吗
非常感谢您的帮助。基本问题是您没有指定自变量。通过为
a、b、tc和t
指定start(…)
,可以告诉nls(…)
,这些都是模型的参数
看起来您使用的是LPPL模型的简化版本,a、b和tc
是参数,t
是自变量。看起来data2$Date
包含时间变量。您需要确保data2$Date
属于POSIXct类。所以你可以写:
df$Date <- as.POSIXct(df$Date, format="%m/%d/%y")
nls1 <- nls(Y~a+b*log(tc-Date), data=data2, start=list(a=0, b=1, tc=1466))
通常,当执行最小二乘回归时,假设存在所谓的“相关”或“响应”变量(
Y
,在您的情况下),它是一个或多个“独立”或“预测”变量(Date
)的函数,通常,预测函数本身的详细说明通常由相当少的静态参数定义(a
和b
,也可能是t
和/或tc
,具体取决于您试图实现的目标)。nls()
函数的任务是为这些静态参数找到最佳值,从而实现尽可能精确的预测
预测函数func
的输入似乎缺少所需的自变量。所以,我认为你可能需要做两件事中的一件。要么修改func
,使其接受Date
作为输入,要么更改数据框中的Date
列标签,使名称与其中一个func
输入匹配(我很可能怀疑您希望重命名Date
列,使其对应于tc
)。在任何一种情况下,如果您想执行一个计算,从固定的偏移日期中减去数据帧中的日期值(例如,(tc-t)
,就像它现在看起来写的那样),您需要检查R是否实际将日期识别为日期对象而不是字符串,所以它知道如何有意义地从一个减去另一个。为此,as.Date()
函数可能会对您有所帮助
作为另一种选择,与其尝试重写func
,使其接受R个日期对象作为输入,您可能会发现,只需参考某个偏移量,将数据框中的Date
列重新指定为经过的整数天就更简单了;e、 例如,做如下事情:
data2$tc <- as.numeric(as.Date(data2$Date) - as.Date("1982-1-4"))
data2$tc非常好的建议,谢谢。它感动了我。当我运行nls1行时,我得到以下错误,-.POSIXt中的错误(tc,Date):只能从“POSIXt”对象中减去。我想这与tc是一个整数而不是一个日期这一事实有关。关于方法论以及为什么选择这个特定的方程式,我正在撰写一篇学术文章来解释其基本原理,@user2926358-请参阅我在上面的编辑:为什么你仍然会出错。有时候这很有趣。我花了一整天的时间研究LPPL建模,并了解您提出的问题。我最初打算尝试你提到的Levenberg-Marquardt算法,但在安装minpack时遇到了问题,所以决定尽量保持简单。通过我今天所做的所有阅读,很明显使用LPPL是一个复杂的问题。感谢您的评论,我将很快开始使用它。几个月前,当我第一次打开R时,上面提到了我正在学习的课程!是的。作为一个新手,我发现这让人困惑,这意味着我无法让它工作,而是使用了na.omit。这对我来说似乎更简单。这很有帮助,谢谢。我选择了你的第三个选项,因为这是最简单的。我完全废除了func,并使用了上面jlhoward的建议。nls1
df$Date <- as.POSIXct(df$Date, format="%m/%d/%y")
nls1 <- nls(Y~a+b*log(tc-Date), data=data2, start=list(a=0, b=1, tc=1466))
# this section just grabs the DJIA for 1982 - 1987; you already have this
library(tseries)
library(zoo)
ts <- get.hist.quote(instrument="DJIA",
start="1982-01-01", end="1987-08-01",
quote="Close", provider="yahoo", origin="1970-01-01",
compression="d", retclass="zoo")
df <- data.frame(ts)
df <- data.frame(Date=as.Date(rownames(df)),Y=df$Close)
df <- df[!is.na(df$Y),]
# end of setup...
library(minpack.lm) # for nls.lm(...)
library(ggplot2) # for ggplot
df$days <- as.numeric(df$Date - df[1,]$Date)
# model based on a list of parameters
f <- function(pars, xx) {pars$a + pars$b*log(pars$tc - xx)}
# residual function
resids <- function(p, observed, xx) {df$Y - f(p,xx)}
# fit using Levenberg-Marquardt algorithm
nls.out <- nls.lm(par=list(a=1,b=-1,tc=5000), fn = resids,
observed = df$Y, xx = df$days)
# use output of L-M algorithm as starting estimates in nls(...)
par <- nls.out$par
nls.final <- nls(Y~a+b*log(tc-days),data=df,
start=c(a=par$a, b=par$b, tc=par$tc))
summary(nls.final) # display statistics of the fit
# append fitted values to df
df$pred <- predict(nls.final)
# plot the results
ggplot(df)+
geom_line(aes(x=Date,y=Y),color="black")+
geom_line(aes(x=Date,y=pred),color="blue",linetype=2)+
labs(title="LPPL Model Applied to DJIA (1982 - 1987)",
x="", y="DJIA (daily close)")+
theme(plot.title=element_text(face="bold"))
data2$tc <- as.numeric(as.Date(data2$Date) - as.Date("1982-1-4"))