How to extract residuals from curvefit - matlab

I'm using curve fit in Matlab R2016a to find the best fit between two arrays. One array represents a certain value at a given latitude and longitude and the other array represents the date that value was collected.
In using the curve fit tool I'm able to find a line of best fit as well as to plot the residuals. The residuals are all I care about-- however, when I export the residuals to the workspace they are represented as one column of numbers. This isn't helpful to me without the identifying information of that residual's relationship to the original arrays (i.e., which X,Y pair does each residual correspond to?)
The data from the residuals graph in the curve fit tool is exactly what I want. Is there a way to export this in a manner that makes it usable?

The cftool uses fit at its heart. What you can do to further explore the fit and its residuals is export the fit to your workspace. Do this through the 'Fit' menu at the top of the Curve Fitting Tool window, then select 'Save to Workspace'. Using this fit object (a cfit for a curve or an sfit for a surface), you can do the same analyses and more as with the curve fitting tool.
Let me illustrate how to obtain a fit, create a plot of the residuals and how to calculate the residuals. The resulting image is shown below. In the code, the residuals variable contains the residuals of the fit with each element belonging to each sample pair in x and y.
% Generate data
rng default
x = sort(rand(10, 1));
y = randn(size(x)) - 3*x;
% Fit a line
fitted = fit(x, y, fittype('poly1'));
% Plot fitted line with data
figure
subplot 311
plot(fitted, x, y)
% Plot residuals
subplot 312
plot(fitted, x, y, 'residuals)')
ylabel residuals
% Get residuals
residuals = y - fitted(x);
% Create stem plot of residuals
subplot 313
stem(x, residuals)
legend residuals
xlabel x
ylabel residuals

Related

matlab: upsampling a zero contour

I am using the undocumented contours function in Matlab to obtain the zero contour of a function mapping R^2 to R. The function contours() calls contourc() to obtain the zero contour in terms of array indices, and contours() then performs linear interpolation to convert from (M,N) array indices to (Y,X) data coordinates. This works well and gives a zero contour which is essentially accurate to machine precision. However, attempting to interpolate along this zero contour to obtain additional points fails, apparently because the interpolated points deviate to a small extent from the true zero contour; the resulting error is too large for the intended application.
As a simple example, one can compute a zero contour of the peaks function, compute the function values along the contour, and then compute the function values at new points interpolated along the contour. The maximum error is roughly eps(max(Z(:)) for the points found by countours/countourc and about ten orders of magnitude higher for the interpolated points.
% compute the zero contours; keep part of one contour
[X,Y,Z] = peaks(999);
XY0 = contours(X, Y, Z, [0 0]);
XY0 = XY0(:,140:(XY0(2,1)+1)); % keep only ascending values in the first contour for interpolation
% interpolate points along the zero contour
x2y = griddedInterpolant(XY0(1,:), XY0(2,:), 'linear','none');
X0i = linspace(XY0(1,1), XY0(1,end), 1e4);
Y0i = x2y(X0i);
% compute values of the function along the zero contour
Zi = interp2(X,Y,Z, XY0(1,:), XY0(2,:), 'linear', NaN);
Z0i = interp2(X,Y,Z, X0i, Y0i, 'linear', NaN);
% plot results
figure;
subplot(1,3,1); plot(XY0(1,:), XY0(2,:), '.'); hold on; plot(X0i, Y0i, 'Linewidth',1);
xlabel('X_0'); ylabel('Y_0'); title('(X_0,Y_0), (X_{0i},Y_{0i})');
subplot(1,3,2); plot(XY0(1,:), Zi, '.');
xlabel('X_0'); ylabel('Z_0'); title('f(X_0,Y_0)');
subplot(1,3,3); plot(XY0(1,:), Zi, '.'); hold on; plot(X0i, Z0i, '.');
xlabel('X_0'); ylabel('Z_0'); title('f(X_{0i},Y_{0i})');
The error is almost certainly because the interpolant does not truly follow the zero contour (i.e., having the same tangent, curvature, and indeed all higher derivatives at each point). Each interpolated point thus deviates to a small degree from the path of the zero contour. This is true for all tested methods of interpolation. If the functional form of the zero contour were known, one could fit a function to the zero contour, which would likely give satisfactory results. However, for the application motivating this question, an analytical solution of the zero contour is not possible.
Given the inadequacy of interpolation to this task, how can new points along the zero contour be obtained? The points should be such that the value of the function is as close to zero as for the set of points returned by contourc. Increasing the grid resolution globally is not an option since the memory and computational expense increase with the square of the resolution. Locally sampling at high resolution in an iterative manner over consecutive short intervals of the zero contour is an option, but would take time to implement, and I'm not aware of existing code (e.g., in the FEX) to perform such a task. Also, since contourc is closed-source, adapting it to this task is not an option.
I solved this problem by taking the interpolated (X,Y) values as an approximation of the true zero contour and reinterpolating the Y coordinate of each pair with respect to Z values of the surface flanking the approximate zero in order to locate the Y coordinate at which Z=0 for each (X,Y) pair. In so doing, uniform spacing of the interpolated X values is preserved.
For each (iX,iY) pair, where iX and iY denote the (fractional) array indices of the X and Y coordinate grids for the points interpolated along the zero contour, the approximate iY values are reinterpolated with respect to the values of Z at positions flanking (in the Y dimension) the approximate zero, i.e., at (iX,floor(iY)) and (iX,ceil(iY)). The Z values at these flanking points are themselves obtained by performing bilinear interpolation of Z at these points.
After reinterpolation, the magnitude of the error is the same as that of the points originally returned by contourc/contours.

How to export fitted curve to 1D vector

With the use of Curve Fitting toolbox I'm fitting to 11 data points a curve described by a custom equation. As a result I get something like this:
I want to save 1D vector represented bye the red line on the plot above into a matlab variable. I try to use Fit->Save to Workspace... option from the Curve Fitting toolbox menu, but saved variables do not contain any of the fitted data.
How can I save fitted data into matlab variable?
The saved MATLAB-object (default name is fittedmodel) contains the fitted function as a function-handle and the fitted coefficients corresponding to this function-handle. You can then evaluate at the data points of your choice with feval.
In the following example the fitted function will be evaluated at the original datapoints x:
y = feval(fittedmodel, x);
Now you can directly plot the result:
plot(x,y);

Plotting cdf and regular graph in same axis in matlab

I have a vector with 1000 random numbers called v. I also have a vector, called x that represents the domain of which the numbers in v are generated, and another vector y that has the numbers of the cdf of the values in v. I know that I can do plot(x,y); and get a smooth function of the (non-empirical) cdf, and I also know that I can do cdfplot(v) to get a function of the empirical cdf.
My question is: How can I get these plots on the same set of axis?
Thank you for your help.
You could either generate data for an empirical cdf plot using ecdf or plot it directly with cdfplot like you mentioned. I would recommend using cdfplot since it sets up a few more things, such as a grid:
hFig = figure;
cdfplot(v);
hold all;
plot(x, y);
And as a bonus! Consider showing the X axis in logarithmic units, whichever reveals the data the best for you:
hAxes = get(hFig, 'CurrentAxes');
set(hAxes, 'XScale', 'log')

Extract data from curve fit toolbox

I am using matlab and I have a certain set of x and y data,
x=[0,1.25,1.88,2.5,5,6.25,6.88,7.19,7.5,10,12.5,15,20];
y=[-85.93,-78.82,-56.95,-34.56,-33.57,-39.64,-41.96,-49.28,-66.6,-66.61,-59.16,-48.78,-41.53];
I want to use the curve fitting toolbox which has the spline function to generate a graph, so i did this,
cftool
It would bring me to the toolbox which i can then choose the spline fit. I was thinking if its possible that i extract the data points from the spline graph generated. Which means i probably would have more x and y data points than those that i input in, since the spline graph is sort of a continuous graph. Anyone could give me some advice on this? Thanks!
You can perform the equivalent of the spline fit performed with cftool with fit, see for instance here, here, or here:
% perform spline fit without cftool
ft = fittype('cubicspline');
coeff=fit(x,y,ft);
% use plot to display the interpolating polynomial
% (relying on internal plot settings)
figure
h=plot(coeff,x,y,'o');
% extract the *interpolated* curve from the figure
xi=get(h,'XData');
yi=get(h,'YData');
Replot it just to show that we can:
But if you just want to interpolate do as Fraukje explained here. Define a finer grid on x and use the interp1 function, as in the following example (same x,y input data as before):
% interpolate
Ni = 100;
xi = linspace(x(1),x(end),Ni);
yi = interp1(x,y,xi,'spline');
Now xi,yi is the interpolated data:

Is there any way to get all points which was drawin on matlab plot

Hi
I was wondering if there is any way to get all points which was drawn on Matlab plot. Let's say that I drawn one line on plot and to draw this line I used just two points - matlab ploter connected these points and I get a line. Is there any way to get all the points which are on that line, without saving this plot to file ??
If you plot a line from two points, e.g. plot([x1 x2],[y1 y2]), the easiest way to get all the plots on the line is to calculate them directly.
nPts = 100; %# number of points on the line you want
%# listOfPoints is a 2-by-nPts array with all the points on the line
listOfPoints = [x1:(x2-x1)/(nPts-1):x2;y1:(y2-y1)/(nPts-1):y2];
You can generate the points you are looking for through basic linear regression. Feed in your x and y variables to Matlab's regression function and it calculates the coefficients of the line of plot(x,y). With the line equation set up, you can feed in a list of new x variables and it will calculate the corresponding y values.
x=[x1; x2];
y=[y1; y2];
b = regress(y,[ones(length(x),1) x])
new_y=b(1)+b(2)*[new_x1:new_x2]