Search code examples
matlabcurve-fittingcurve

How to fit a curve on a discrete sequence data (stem) in Matlab?


I have two matricesFDX and TDX (two classes) with dim: 2xn, that FDX(1, :), FDX(2, :) are the number of objects and mean of them, respectively (also for TDX). I plot the above discrete sequence data using stem and now I want to show a curve instead of its lines to create a density map from points (like a pdf) or (like fit a curve to a Histogram), to better comparing between two classes.

Is there any way to fit a curve on the following plot of stem in Matlab?

I have also seen some links like link1 and also link2 but they are about histogram or continues data. Also, I have used the fit curve (link instead of the stem but two created curves are confusing.

Example:

FDX = [9,12,7,7,8,4,10,8,5,9,10; 0.626023067402372,0.647560923068733,0.266314729708634,0.512920709657816,0.408389652529404,0.444588941849425,0.800367166464757,1.28429713933315,0.391101796334982,0.219880153736852,0.439931802866314];
TDX = [1,1,2,1,1,1,1,1,1,1,1; 0.0888514059469934,0.0730468099283854,0.246560340244561,0.300711548987410,0.0871198693779434,3.11190476190476,0.185185185185183,0.246964650258985,0.113415750915749,0.132034632034618,0.201388888888900];


f1 = fit(TDX(2, :)', TDX(1, :)','smoothingspline');
plot(f1,'b', TDX(2, :)', TDX(1, :)','oc');
hold on
% stem(TDX(2, :), TDX(1, :),'*c');
grid on   
hold on


f2 = fit(FDX(2, :)', FDX(1, :)','smoothingspline');
plot(f2,'r',FDX(2, :)', FDX(1, :)','om');
hold on
% stem(FDX(2, :), FDX(1, :),'*m');
grid on   
hold off

title('Displacement Curve X', 'Units', 'normalized', 'Position', [2.5, 1.1, 0]); 
xlabel('Mean')
ylabel('Number of Objs')
legend('MeanTDX','MeanFDX')
set(gcf, 'Units', 'Normalized', 'OuterPosition', [0 0 1 1]);

In the following, there are two plots of FDX and TDX with dimensions of 2x432 and 2x114, respectively. and

Output of stem:

enter image description here

Output of fit:

enter image description here

A model that I want:

enter image description here


Solution

  • You can use the curve fitting toolbox, which provides really nice features. Since you didn't specify a specific model you would like to use, I just assumed you have normal distributed data (similar to your "output of stem" image). But you can use the fittype() function to basically specify any model you want. Check here for infos regarding its parameters. Also think about the model you choose, it should resonably represent the data.

    For simplicity I chose to use some sample data, but hopefully it will also work with your real data and the model you want.

    points = 100;
    x = -points:points;
    y = normpdf(x, -20, 20);
    n = -0.01+2*0.01*rand(size(x));
    y = y+n; % invent some noisy normal distributed test data
    
    [xData, yData] = prepareCurveData(x, y);
    
    % Set up fittype and options. (here assume normal dist)
    ft = fittype(@(u, s, x)(1/(s*sqrt(2*pi))*exp(-(x-u).^2/(2*s^2))), 'coefficients', {'u', 's'}, 'independent', 'x', 'dependent', 'y')
    
    % Fit model to data.
    [fitresult, gof] = fit(xData, yData, ft);
    
    % Plot fit with data.
    figure
    h = plot(fitresult, xData, yData);
    legend(h, 'data', 'fit', 'Location', 'NorthEast');
    xlabel('x'); ylabel('y'); grid on
    
    % Extract the equation(ft) and the coefficients
    coeffnames(fitresult)
    coeffvalues(fitresult)
    

    fit plot

    This should also work in case you use stem to display your data.

    fit plot using stem