How to extrapolate an x value from a fitting curve?

Hello everyone,
I'm kind new to Matlab.
I have a set of data, from which I obtained a fitting curve by interpolation using Fitting Curve toolbox. This is the essential code I'm using:
%example values
xvalues = [10; 12; 22; 28]
yvalues = [1; 2; 3; 4]
% Fit model to data.
[fitresult, gof] = fit( xvalues, yvalues, 'linearinterp', 'Normalize', 'on' );
% Plot fit with data.
figure( 'Name', 'untitled fit 1' );
h = plot( fitresult, xvalues, yvalues );
Later, I would like to obtain the exact value from the fitting curve at a certain value on the y axis (that, obviously, is not contained in the yvalues vector). The problem is that the fit function does not return "fitresult" as a vector, so i don't know hot to do that. I know that it could be easily done graphically, but i need a code to automatize the process. What could I try?
I attach an image as graphical explanation:
EDIT
  • I want to get an x value from a known y value;
  • I can't use interp1 for what I know, because "fitresult" is a cfit and it is not a vector;
  • I can't use x(fitresult==y_known_value) because it would return the error: "Operator '==' is not supported for operands of type 'cfit' ".
  • Found a similiar problem here: Getting x for a given y value from a cfit object - MATLAB Answers - MATLAB Central (mathworks.com), I followed Steven Lord's method and I got this solved. The exact code is posted as answer to this topic.
Thank you all for help!

Answers (4)

feval(fitresult,xvalue)

1 Comment

Thank you, but here we have the same problem as the answer from dpb:
as you can see from the image I posted, I know the y value and I want to get the corresponding x value. So, using feval would not work, 'cause xvalue is what I want to get, and it can't be my input.

Sign in to comment.

xvalues = [10; 12; 22; 28];
yvalues = [1; 2; 3; 4];
% Fit model to data.
[fitresult, gof] = fit( xvalues, yvalues, 'linearinterp', 'Normalize', 'on' );
h = plot( fitresult, xvalues, yvalues );
hold on
X=25;
hP=plot(X,fitresult(X),'k*');
hF=gcf; hLg=findobj(hF,'type','Legend');
hLg.Location='northwest';
See fit documentation; the fit object evaluates the fit automagically for the points passed it...

3 Comments

Thank you, but in your example you're giving a value from the x axis as it is known, to get the corresponding value on the y axis.
I have to do exactly the opposite: as you can see from the image I posted, I know the y value and I want to get the corresponding x value. So, writing fitresult(x_value) would not work.
The problem here, maybe, is that I want to get a value from the indipendet variable knowing the dependent one; and i can't use interp1 (I think) because I don't have a vector.
OK, I overlooked the original intent, sorry.
Since you're interpolating and not fitting a single expression, the resultant fit object is a piecewise polynomial and since it is linear and you're interpolating, then there's no reason to not just simply use interp1 on the original input data in the backwards lookup...
xvalues = [10; 12; 22; 28];
yvalues=[1:4].';
Y=3.5;
X=interp1(yvalues,xvalues,Y)
X = 25
Now, direct interpolation of your y-values vector with interp1 will mean it will have to be monotonic and unique; if that may not be so in the final dataset, then simply redo the fit t'other way 'round; I believe it will handle that case with the p-p instead (but I didn't test it).
xvalues = [10; 12; 22; 28; 12];
yvalues=[1:4 0].';
fitrev=fit(yvalues,xvalues,'linearinterp','Normalize', 'on' );
Y=3.5;
X=fitrev(Y)
X = 25
And, indeed, the pp serves the trick with non-monotonic data values -- although as @Star Strider notes, it would require deciding which section of the overall the lookup value is supposed to be in to get the result between 28;12 instead of that between 22;28 in the above.
Only you know what the real application is....

Sign in to comment.

You can eliminate the monotonicity problem by first selecting the region of the desired value —
xvalues = [10; 12; 22; 28];
yvalues = [1; 2; 3; 4];
yq = 3.5;
idx = find(diff(sign(yvalues - yq)));
ixr = [-1 0 1]+idx;
xq = interp1(yvalues(ixr), xvalues(ixr), yq)
xq = 25
A more robust approach to defining ‘ixr’ (and the interpolation results), especially if it contains more than one value, is:
for k = 1:numel(idx)
ixr = max(1,idx(k)-1) : min(numel(xvalues),idx(k)+1);
xq(k) = interp1(yvalues(ixr), xvalues(ixr), yq)
end
xq = 25
This prevents ‘ixr’ from referencing indices beyond the index range of the vectors being interpolated.
.
Bruno Galizia
Bruno Galizia on 24 Oct 2022
Edited: Bruno Galizia on 24 Oct 2022
Thank you all for your answers.
Anyway, I got a working code by checking here:
So, that's what I did:
xvalues = [10; 12; 22; 28]
yvalues = [1; 2; 3; 4]
y_known = 3.5950
% Fit model to data.
[fitresult, gof] = fit( xvalues, yvalues, 'linearinterp', 'Normalize', 'on' );
ftogetx = @(x) y_known - fitresult(x);
x_to_find = fzero(ftogetx, 0)
plot(fitresult, xvalues, yvalues)
hold on
plot(x_to_find, y_known, "k*")

1 Comment

Running that for the record —
xvalues = [10; 12; 22; 28]
xvalues = 4×1
10 12 22 28
yvalues = [1; 2; 3; 4]
yvalues = 4×1
1 2 3 4
y_known = 3.5950
y_known = 3.5950
% Fit model to data.
[fitresult, gof] = fit( xvalues, yvalues, 'linearinterp', 'Normalize', 'on' );
ftogetx = @(x) y_known - fitresult(x);
x_to_find = fzero(ftogetx, 0)
x_to_find = 25.5700
plot(fitresult, xvalues, yvalues)
hold on
plot(x_to_find, y_known, "k*")
.

Sign in to comment.

Categories

Products

Release

R2022a

Asked:

on 24 Oct 2022

Commented:

on 24 Oct 2022

Community Treasure Hunt

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

Start Hunting!