polyfit does not seem to fit data very well in matlab - matlab

I am using polyfit in matlab to plot a straight line of best fit through points. However, the best fit line is not as I would expect - the line does not look like it fits the data very well... does it? Here's my code, any help with improving this would be great. (Note, the axis limits I have set are important).
x = [0 1 10 5 1 1.5];
y = [-14 -18 -22 -26 -30 -34];
scatter(x,y)
hold on
p = polyfit(x,y,1);
f = polyval(p,x);
plot(x,f,'-r','linewidth',1.2)
ylim([-35 -10])
xlim([-30 30])

Your fit looks proper to me, but this might be what you're looking for instead
x = [0 1 10 5 1 1.5];
y = [-14 -18 -22 -26 -30 -34];
scatter(x,y)
hold on
p = polyfit(y,x,1);
f = polyval(p,y);
plot(f,y,'-r','linewidth',1.2)
ylim([-35 -10])
xlim([-30 30])

Here's a total least squares solution
data=[x(:), y(:)];
c=mean(data);
data=bsxfun(#minus,data,c);
[~,~,v]=svd(data);
d=v(:,end);
k=dot(d,c);
ezplot(#(x,y) x*d(1)+ y*d(2)-k, [-30 30 -35 -10])

Related

Color some samples of MATLAB figure with different color

I have a discrete signal x of length N traced in MATLAB using the command
stem(abs(x)); axis([0 N+6 0 4]);
The resulted figure is shown below:
My question I need only some values corresponding for example to index [7 10 11 12 15 18 48 50 52 60] to be colored with different color , let's say with red.
How can I do that into my figure ?
Using Multiple Plots by hold on and Matrix Indexing
You could possibly and alternatively place a plot on top of plot by using hold on. This does require an adjustment where you need a vector in this case Sample and Indices which specify the sample number/data point index. You can also use matrix indexing to get the amplitude/data points corresponding to the key point, Indicies.
%Vector relating to the sample/data point number%
Sample = linspace(1,70,70);
%Random test data%
X = randi([0,2],1,70);
stem(Sample,X);
hold on
%Key indices to change colour%
Key_Indices = [7 10 11 12 15 18 48 50 52 60];
%Matrix indexing to get values/amplitudes corresponding to key indices%
X_Prime = X(Key_Indices);
stem(Key_Indices,X_Prime,'r');
axis([0 70 0 3]);
hold off
Ran using MATLAB R2019b
This code makes just the circles red and not the stems
plot with selected red circles
%Vector relating to the sample/data point number
Sample = linspace(1,70,70);
%Random test data
X = randi([0,2],1,70);
stem(Sample,X);
%Key indices to change color
Key_Indices = [7 10 11 12 15 18 48 50 52 60];
line(Sample(Key_Indices), X(Key_Indices), 'linestyle', 'none', 'marker', 'o', 'color', 'r')
axis([0 70 0 3])
grid on

Curve fitting for non-linear data

I am trying to fit some data using lsqcurvefit in MATLAB but I am fairly new to this area.
xdata1 = [0 60 660 1250];
ydata1 = [0 18 23 31];
In the image below, the red line is the fit I want to achieve.
How can I achieve this fit?
How about polyfit() ?
Code here:
close all % be careful with following two lines
clear all
x = [0 60 660 1250];
y = [0 18 23 31];
p = polyfit(x,y,3);
xx = linspace(x(1), x(end), 100);
yy = polyval(p,xx);
plot(x,y,'o'); hold on; plot(xx,yy)

understanding patch behavior

I do not understand why patch does not follow the lines in this image:
In fact, in the code I used, the lines and the patch share the same input variables X and Y:
clearvars
close all
clc
figure(1)
z=peaks(50);
% Create x,y coordinates of the data
[x,y]=meshgrid(1:50);
% Plot Data and the slicing curve
surf(z);
hold on
X=[1 21 35 47 29 25 8];
Y=[5 19 24 26 14 39 47];
plot3(X,Y,-10*ones(1,numel(X)),'r','linewidth',3);
plot3(X,Y,10*ones(1,numel(X)),'r','linewidth',3);
patch([X fliplr(X)],[Y fliplr(Y)],[-10*ones(1,numel(X)) 10*ones(1,numel(X))],...
'r','FaceAlpha',0.21)
axis([0 50 0 50])
What am I messing up?
You pass the wrong arguments to patch. The Matlab documentation says that
If XData is a matrix, then each column represents the x-coordinates of a single face of the patch.
Thus, the patch data should look like this:
XData= [
X(1) X(2) ... and so on
X(2) X(3)
X(2) X(3)
X(1) X(2)];
YData= [
Y(1) Y(2) ...
Y(2) Y(3)
Y(2) Y(3)
Y(1) Y(2)];
ZData= [
-10 -10 ...
-10 -10
10 10
10 10];
You can use patch this way:
patch([X(1:end-1);X(2:end);X(2:end);X(1:end-1)],[Y(1:end-1);Y(2:end);Y(2:end);Y(1:end-1)],...
[-10*ones(1,numel(X)-1);-10*ones(1,numel(X)-1);10*ones(1,numel(X)-1);10*ones(1,numel(X)-1)],...
'r','FaceAlpha',0.21)
or you can use surf:
surf([X;X],[Y;Y],[-10*ones(1,numel(X)) ;10*ones(1,numel(X))],'FaceAlpha',0.21);

Wavelenth vs Absorbance plot in MATLAB

I have a number of wavelengths and their corresponding absorbances.
First I entered the x and y values
x = [400 425 450 475 500 505 510 525];
y = [.24 .382 .486 .574 .608 .608 .602 .508];
To plot the points
plot(x, y, 'o')
Then I want to fit the data.
I'm not sure what degree of polynomial to choose, but since it's a plot of Wavelength vs Absorbtion, wont there already be a mathematical formula? Like how you know a plot of Kinetic energy vs Velocity will be degree 2 because KE = 1/2mv^2?
Alright so here is a solution that works fine with your data, using polyfit and polyval to evaluate a polynomial that passes through your data points.
In the doc for polyfit (here), it states that
In general, for n points, you can fit a polynomial of degree n-1 to
exactly pass through the points.
Since you have 8 data points, we can try using a polynomial of degree 7 and see what it givesL
clear
clc
x = [400 425 450 475 500 505 510 525];
y = [.24 .382 .486 .574 .608 .608 .602 .508];
%// Get polynomial coefficients to fit the data
p = polyfit(x,y,7)
%// Create polynomial to plot
fFit = polyval(p,x);
plot(x,y,'o')
hold on
plot(x,fFit,'r--')
hold off
axis([400 525 0 .7]);
legend({'Data points' 'Fitted curve'},'Location','NorthWest')
gives this:
So it does look to work very well! If we look at the coefficients given by polyfit:
p =
1.0e+05 *
Columns 1 through 6
0.0000 -0.0000 0.0000 -0.0000 0.0000 -0.0003
Columns 7 through 8
0.0401 -2.7206
Maybe the degree 7 was a bit overkill since the first 5 coefficients are 0 ( or about 0), but anyhow it fits very well!
Hope that helps!

how to get value between points from a plot?

Consider that I have the following sets of values,
Y = [1 23 4 67 89 23 5 12 ]
X = [0 2 4 6 10 14 18 22 ]
I can draw a plot with the basic plot function. Now, from this plot, I want to know what the Y value for X=5. How can I get this data?
You can see, it's not part of my plot points, but something I was to extract from the graph.
Any ideas folks? I'm a bit surprised that there isn't a built in function for this.
The function you are looking for is interp1
For your example, the code would be
y = interp1(X, Y, 5, 'linear');
Since plot uses linear interpolation, you should use it as well.
y = interp1(X,Y,5);