Curve fit or spline fit for a wavy function

4 views (last 30 days)
I have a data for which I need to fit a curve. The original data and the curve fit which I got using a 2nd order polynomial are shown below.
However, I need the fitted curve to be a smooth curve which lays on top of the original data (same form). What would be the best way to do it?
Thanks!

Accepted Answer

John D'Errico
John D'Errico on 6 Dec 2020
Edited: John D'Errico on 6 Dec 2020
If you really want help, then do several things.
  1. Provide your data, or a good example of it. Attach it in a .mat file to a comment or to your original question.
  2. Explain CLEARLY what you mean by fit, and what will be the purpose of this fit. What will you do with this curve fit? Do you just want a smooth curve that passes through the data as well as possible, while smoothing out the noise we see? A nice plot? Will you use it for predictive purposes? Do you want some pretty functional form you can write down in a report?
That is, if you just want a reasonably smooth non-parametric curve drawn thrrough the data, then a good choice is something like a Savitsky Golay smooth. There are many other ways to do so too. You will NOT get any nice function out of this though.
If you want to draw a curve, and then use it for future purposes, I might recommend a least squares apline, or a smoothing spline. You can evaluate that spline at any point for predictive purposes. But again, a spline is NOT a model you can write down and have it look remotely pretty in a report. While you could write something down, that would take multiple pages just to write it all out.
Finally, you could postulate a nonlinear model, then estimate the coefficients of that model. It might fit reasonably well, but it will surely not be as good of a fit as the alternatives I have already recommended.
  5 Comments
John D'Errico
John D'Errico on 7 Dec 2020
I don't think you paid any attention to what I said. You can evaluate the curve at ANY set of points. So what is the problem? I showed you eactly how to do that evaluation. Hint - what do you think these lines do:
spl(t)
or
slmeval(t,SLM)
Depending on which method you use for the fit.
Can you use polyfit otr polyval? NOOOOOOOOOOO!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
NO.
NO.
NO.
NO.
NO. PERIOD.
The curve you should completely lacks polynomial behavior. The result will be pure crap.
Siddharth Gopujkar
Siddharth Gopujkar on 7 Dec 2020
Ok, I uderstood now. It works!
Thank you so much, John!

Sign in to comment.

More Answers (3)

Ameer Hamza
Ameer Hamza on 6 Dec 2020
Use interp1(): https://www.mathworks.com/help/matlab/ref/interp1.html with 'spline' interpolation method.
  1 Comment
John D'Errico
John D'Errico on 6 Dec 2020
Edited: John D'Errico on 6 Dec 2020
Note: this appears to be noisy data. interpolating splines tend to be bad ideas for noisy data. They don't smooth out the bumps, but in fact, will oscillate more wildly in the presence of noise.

Sign in to comment.


Image Analyst
Image Analyst on 6 Dec 2020
Edited: Image Analyst on 6 Dec 2020
I'd simly use sgolayfilt() if you have the Signal Processing Toolbox. It's like a scanning polynomial filter. Pick an appropriate window, like 20 elements or whatever, and polynomial order, like 2 for quadratic, and get out the smoothed signal.
See 3 attached demos.
Attach your data if you need more help.
  4 Comments
Siddharth Gopujkar
Siddharth Gopujkar on 6 Dec 2020
Thanks for this!
The plot looks good, but the filtered signal needs to have the same number of values as the vector 't'. So the filtered signal needs 98304 values.
Image Analyst
Image Analyst on 7 Dec 2020
Well you posted 2 arrays, time and RPM both of which have 3670 elements, and one array t which has 983041 elements. Since you can't plot a 3670 RPM vs a 983041 element "t", I assumed the x axis was time and the y value was RPM and they matched up element for element. And the smoothed signal filteredSignal has the same number of elements as time and RPM, as it should.
One problem is that the range of t and time don't cover the same range, so you can't get values for RPM that are less than time(1) or more than time(end). They will show up as nan since there is nothing in RPM to interpolate in that range. But you can just simply add the line
filteredSignal2 = interp1(time, filteredSignal, t);
and get the values of filteredSignal for every value of t that is within the original time series which matches up with RPM. Again, if you have no values of RPM for those t, then the values will be nan there. Here is the new code:
% Read in and plot the original signal
load('RPM.mat')
load('t.mat')
load('Time.mat')
subplot(1, 2, 1);
plot(time, RPM,'r-','Linewidth',1)
title('Original Signal', 'fontSize', 20);
xlabel('t', 'fontSize', 20);
ylabel('RPM', 'fontSize', 20);
grid on;
% Filter the signal. Just one line of code!
filteredSignal = sgolayfilt(RPM, 2, 101); % 3670 elements.
filteredSignal2 = interp1(time, filteredSignal, t); % 983041 elements
% Done! Now make a fancy plot.
subplot(1, 2, 2);
plot(t, filteredSignal2,'b-','Linewidth',1)
title('Filtered Signal', 'fontSize', 20);
xlabel('t', 'fontSize', 20);
ylabel('RPM', 'fontSize', 20);
grid on;
g = gcf;
g.WindowState = 'maximized'

Sign in to comment.


Bruno Luong
Bruno Luong on 6 Dec 2020
Edited: Bruno Luong on 6 Dec 2020
You can use my tool
load('RPM.mat')
load('t.mat')
load('Time.mat')
% https://www.mathworks.com/matlabcentral/fileexchange/25872-free-knot-spline-approximation
pp = BSFK(time,RPM);
rpm = ppval(pp,t);
%plot(time,RPM,'b')
% hold on
plot(t,rpm,'r','Linewidth',1)

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!