How to extrapolate an x value from a fitting curve?

117 views (last 30 days)
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)

David Hill
David Hill on 24 Oct 2022
feval(fitresult,xvalue)
  1 Comment
Bruno Galizia
Bruno Galizia on 24 Oct 2022
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.


dpb
dpb on 24 Oct 2022
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
dpb
dpb on 24 Oct 2022
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).
dpb
dpb on 24 Oct 2022
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.


Star Strider
Star Strider on 24 Oct 2022
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
Star Strider
Star Strider on 24 Oct 2022
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.

Products


Release

R2022a

Community Treasure Hunt

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

Start Hunting!