[R] fitting sine wave
djmuser at gmail.com
Thu Jul 28 01:06:01 CEST 2011
This is a linear model since you have no nonlinear term *in the
parameters*. The model you postulated is as far as you can go since
you have 1 df for error (unless you remove the intercept term). As the
plot below shows, a linear model does not fit the data well -
basically, it provides a quadratic approximation to the data, which is
clearly inadequate, but is reasonable in the sense that a linear model
is trying to capture the mean value of Y as a function of X and the
data 'look' quadratic (with a lot of variation). [Check out the
adjusted R^2 in summary(sr1) :) ] Removing the intercept provides more
curvature in the fitted values, but that's not necessarily a good
I'd suggest trying to fit a spline, but without any information
between the peaks and valleys, it's unlikely that you could come up
with anything better than a sawtooth shaped function (linear spline).
*Maybe* you could do a little better using the x-values corresponding
to the local maxima as knots, but degrees of freedom for error is
certainly going to be a problem, just as it was for the linear model.
As it appears you want to fit the first two terms of a Fourier series,
fft() could be a reasonable alternative, but AFAIK there is a
distinction between a Fourier series expansion and a Fourier transform
of a function. Since I'm no expert on Fourier series and my exposure
to Fourier transforms is limited to its applications in probability
theory, I'll refrain from commenting on that aspect of the problem.
It is reasonable to ask whether the first two terms of the Fourier
series expansion is sufficient to encapsulate the essential features
of the true function, though.
Reporting only the min and max of a cycle leaves out a lot of
information about the form of the underlying function, so it shouldn't
be surprising if a statistical model fails to capture the true
structure of the underlying function, especially if it's periodic.
# -- code to fit and plot the results of a linear model
m <- c(-0.2061826,0.5888406,0.2026079,1.0000000,0.2342754,0.6865078,-0.1265754)
x <- 1:7
d <- data.frame(x, m)
sr1 <- lm(m ~ x + cos(x) + sin(x) + cos(2 * x) + sin(2 * x), data = d)
sr0 <- update(sr1, . ~ . - 1)
psx <- data.frame(x = seq(1, 7, length = 500))
psp1 <- data.frame(psx, yhat = predict(sr1, newdata = psx))
psp0 <- data.frame(psx, yhat = predict(sr0, newdata = psx))
plot(m ~ x, data = d)
lines(yhat ~ x, data = psp1) # linear model with intercept
lines(yhat ~ x, data = psp0, col = 'blue') # without intercept
On Wed, Jul 27, 2011 at 7:36 AM, Tonja Krueger <tonja.krueger at web.de> wrote:
> Dear R-helpers
> I have 7 data points that I want to fit a continuous curve to, that should look similar to a sine wave
> My data points would mark the local minima and maxima respectively.
> This is what I’ve got so far. And I would keep doing so, but sadly nls() then says that it has reached the maximum number of Iterations…
> x <- c(1,2,3,4,5,6,7)
> p <- nls(m~k1*x+k2*cos(x)+k3*sin(x)+k4*cos(2*x)+k5*sin(2*x)+k6*cos(3*x),start = list(k1=0,k2=0,k3=0.1,k4=0.1,k5=0,k6=0))
> par <- c(pk1=summary(p)$parameters[1,1],pk2=summary(p)$parameters[2,1],pk3=summary(p)$parameters[3,1],pk4=summary(p)$parameters[4,1],pk5=summary(p)$parameters[5,1],pk6=summary(p)$parameters[6,1])
> xx <- seq(1,7,length.out=500)
> mm <- par*xx+par*cos(xx)+par*sin(xx)+par*cos(2*xx)+par*sin(2*xx)+par*cos(3*xx)
> I was also thinking of using fft(), but when I use the inverse function I only get my 7 original points back, but no smooth sine function.
> Thank you for your suggestions.
> Schon gehört? WEB.DE hat einen genialen Phishing-Filter in die
> R-help at r-project.org mailing list
> PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
> and provide commented, minimal, self-contained, reproducible code.
More information about the R-help