0

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

Ellie
  • 303
  • 2
  • 16
  • 2
    are you fitting or just interpolating\smoothing with spline based on the data? I dont see a fit model or expression ? – bla Sep 06 '19 at 21:40
  • 1
    I suggest trying a combined power and exponential equation, "y = a * pow(x, b) * exp(c * x)". Good initial parameter estimates for fitting appear to be a = 5.0E+03, b = 3.1E+00, and c = -5.6E+00 – James Phillips Sep 07 '19 at 11:31
  • @James Phillips: I can't define 'y' because there are both of x and y. Ex: `y = FDX(1,:)`; and `x = FDX(2,:)`; and also for `TDX`. – Ellie Sep 07 '19 at 13:27
  • I understand - I had simply used data extracted from the posted scatterplot, which has the appearance of x and y data. – James Phillips Sep 07 '19 at 14:02
  • @bla: I don't know which method is needed, but I want a model to show the density of points (two curves for two classes). I have also seen `csaps` function and `pchip` functions in Mathwork, but I don't know how to use them for my vectors. I wrote a script for my data and an error occurred, `The data sites should be distinct`. – Ellie Sep 07 '19 at 14:18

1 Answers1

2

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

avermaet
  • 1,543
  • 12
  • 33
  • I used your script for my data but the curve didn't fit well on the points. It is a curve with low Kurtosis. – Ellie Sep 07 '19 at 10:54
  • 1
    @eli I see. This is possible, but depends on your data. Curve fitting finds the curve with the least error between the data points and the curve, which doesn't mean that the curve will be "above" the points you have. This method of fitting is also what is wanted usually since the resulting curve best describes the data (= least error). In the new image of your desired curves that you added to your question, you drew the curves above nearly all points, so the total error won't be minimal. I guess this can't be what you want. – avermaet Sep 07 '19 at 21:33
  • Yes, the new image of my desired curves is edited. Your suggestion is a curve that I want, but it has low Kurtosis for my data. But I want to know, What is the difference between 'histfit' function that constructs a histogram with a normal distribution and my problem? Is using a function like 'histfit', possible for my data? – Ellie Sep 08 '19 at 10:24
  • 1
    I think you could also use `histfit`for your purpose. But in general `histfit` has the disadvatage that it only fits distributions, whereas my code can fit any function/model. I assume if you use `histfit` with a normal distribution it is very similar to my code applied directly to your data (both a fitting of a normal distribution to your data). But I'm not 100% sure if the number of pins you choose in `histfit` will affect your result. So maybe `fitdist` is even better for you. – avermaet Sep 08 '19 at 13:16