2013-11-20 128 views
7

我是一个初学者,在曲线拟合和Stackoverflow上的几个帖子真的帮助了我。在R中使用lm和nls的正弦曲线拟合

我试图使用lmnls来拟合我的数据的正弦曲线,但是这两种方法都显示出奇怪的拟合,如下所示。任何人都可以指出我出错的地方。我会怀疑有时间做的事情,但无法做到。我的数据可以从here访问。 plot

data <- read.table(file="900days.txt", header=TRUE, sep="") 
time<-data$time 
temperature<-data$temperature 

#lm fitting 
xc<-cos(2*pi*time/366) 
xs<-sin(2*pi*time/366) 
fit.lm<-lm(temperature~xc+xs) 
summary(fit.lm) 
plot(temp~time, data=data, xlim=c(1, 900)) 
par(new=TRUE) 
plot(fit.lm$fitted, type="l", col="red", xlim=c(1, 900), pch=19, ann=FALSE, xaxt="n", 
yaxt="n") 

#nls fitting 
fit.nls<-nls(temp~C+alpha*sin(W*time+phi), 
    start=list(C=27.63415, alpha=27.886, W=0.0652, phi=14.9286)) 
summary(fit.nls) 
plot(fit.nls$fitted, type="l", col="red", xlim=c(1, 900), pch=19, ann=FALSE, xaxt="n", 
axt="n") 
+0

'fit.lm'属于类“lm”,所以有一个绘图方法。 'plot(fit.lm,type .....)'可能更符合你的要求。 –

+0

“366”来自公式2 * pi * time/366的意义是什么? – Vinterwoo

回答

9

这是因为NA的值已从要修改的数据中移除(并且您的数据有相当多的数据);因此,当您绘制fit.lm$fitted时,绘图方法将该系列的索引解释为“x”值以对其进行绘制。

试试这个[注意我是如何改变的变量名,以防止冲突与功能timedata(读this后)]:

Data <- read.table(file="900days.txt", header=TRUE, sep="") 
Time <- Data$time 
temperature <- Data$temperature 

xc<-cos(2*pi*Time/366) 
xs<-sin(2*pi*Time/366) 
fit.lm <- lm(temperature~xc+xs) 

# access the fitted series (for plotting) 
fit <- fitted(fit.lm) 

# find predictions for original time series 
pred <- predict(fit.lm, newdata=data.frame(Time=Time))  

plot(temperature ~ Time, data= Data, xlim=c(1, 900)) 
lines(fit, col="red") 
lines(Time, pred, col="blue") 

这给了我:

enter image description here

这可能是你所希望的。

+0

我只是想知道如何改进,使曲线实际上符合最高温度值。 – Eddie

+0

@Eddie我不确定你的意思。你能澄清吗? –

+1

再次感谢@Andy Barbour,我希望蓝色曲线通过一些最大值(例如,在第一个峰值29.5摄氏度)。目前,预测的最高峰(​​蓝色曲线)约在28.8摄氏度左右。我不确定如何在lm中对此进行优化。对于nls,我认为我可以通过改变我的初始参数值(这也是一个棘手的部分)来实现这一点。 :) – Eddie

4

如何选择一个X和Ÿ,而这样做你的线图,而不是只选择Y.

plot(time,predict(fit.nls),type="l", col="red", xlim=c(1, 900), pch=19, ann=FALSE, xaxt="n", 
yaxt="n") 

还兼具lmnls只是给你的拟合点。所以你必须估计其余的点以便绘制一条曲线,一条线图。由于您使用的是nlslm,因此功能predict也许有用。

1

不知道这可能会帮助 - 我只得到了类似的使用配合正弦:

y = amplitude * sin(pi * (x - center)/width) + Offset 

amplitude = 2.0009690806953033E+00 
center = -2.5813588834888215E+01 
width = 1.8077550471975817E+02 
Offset = 2.6872265116104828E+01 

Fitting target of lowest sum of squared absolute error = 3.6755174406241423E+01 

Degrees of freedom (error): 90 
Degrees of freedom (regression): 3 
Chi-squared: 36.7551744062 
R-squared: 0.816419142696 
R-squared adjusted: 0.810299780786 
Model F-statistic: 133.415731033 
Model F-statistic p-value: 1.11022302463e-16 
Model log-likelihood: -89.2464811027 
AIC: 1.98396768304 
BIC: 2.09219299292 
Root Mean Squared Error (RMSE): 0.625309918107 

amplitude = 2.0009690806953033E+00 
     std err squared: 1.03828E-02 
     t-stat: 1.96374E+01 
     p-stat: 0.00000E+00 
     95% confidence intervals: [1.79853E+00, 2.20340E+00] 
center = -2.5813588834888215E+01 
     std err squared: 2.98349E+01 
     t-stat: -4.72592E+00 
     p-stat: 8.41245E-06 
     95% confidence intervals: [-3.66651E+01, -1.49621E+01] 
width = 1.8077550471975817E+02 
     std err squared: 3.54835E+00 
     t-stat: 9.59680E+01 
     p-stat: 0.00000E+00 
     95% confidence intervals: [1.77033E+02, 1.84518E+02] 
Offset = 2.6872265116104828E+01 
     std err squared: 5.15458E-03 
     t-stat: 3.74289E+02 
     p-stat: 0.00000E+00 
     95% confidence intervals: [2.67296E+01, 2.70149E+01] 

Coefficient Covariance Matrix 
[ 0.02542366 0.01786683 -0.05016085 -0.00652111] 
[ 1.78668314e-02 7.30548346e+01 -2.18160818e+01 1.24965136e-01] 
[ -5.01608451e-02 -2.18160818e+01 8.68860810e+00 -1.27401806e-02] 
[-0.00652111 0.12496514 -0.01274018 0.0126217 ] 

詹姆斯·菲利普斯 [email protected]

+1

谢谢@詹姆斯菲利普斯。确实如此。你可能想检查这篇文章http://stats.stackexchange.com/questions/60500/how-to-find-a-good-fit-for-semi-sinusoidal-model-in-r – Eddie

0

或者,你可以从你的数据中消除在NAS在看完后:

data <- subset(data, !is.na(temperature)) 

然后,打印时,您可以将X轴设定为缩减数据集合的时间点:

plot(temp~time, data=data, xlim=c(1, 900)) 
lines(x=time, y=fit.lm$fitted, col="red") 

这条曲线不会像@ andy-barbour生成的曲线那么平滑,但它可以在捏合中工作。