plotting a seperately defined function

Dear community,
My problem is that i don't know how to plot a separately defined function, which is divided into different sections.
In the example below, it is obvious that MATLAB checks the condition only once and outputs the x-value +1 for all x-values.
The goal is that the function
in the interval [1,2) is defined by x+1
in the interval [2,3) is defined by x+2
in the interval [3,4) by x+3 etc.
The function described here is a minimal example.
I am appreciated for any help.
The plot is blue and the function as it should look is pink (excuse the inaccurate drawing, I hope it is clear what is meant).
x=1:0.001:8;
v=[0 1 2 3 4 5 6 7 8];
plot(x,test(x,v),'color',[.25 .75 1],'LineWidth',2)
%--------------------------------------------------------------
% seperate .m file
function y = test(time,value)
t = intervall(time,value) ;
y = time+value(t);
end
%-------------------------------------------------------------
% seperate .m file
function int = intervall(time,boundary)
j = 2;
while boundary(j) <= time
j=j+1;
end
int = j-1;
end

Risposte (1)

function int = intervall(time,boundary)
int = interp1(boundary, time*(1+eps), 'next') - 1;
end
This depends upon the boundary values being in ascending order.
interp1(A,B,'next') finds the index of (each) B in A such that B <= A(index) -- so if B is not found exactly then it finds the "next" value in the matrix and gives back the index. If the boundaries were [0 1 2] and the input was exactly 1, the output of the interp1() would be 2, since 1 <= A(2) = 1. Likewise, input of 1.1 would give back index 3. since A(2) < 1.1 and 1.1 <= A(3)
But your original code scans until it finds a value that is after an equality and then steps back 1, whereas this code would stop at the equality. Your code would take the 1 and the 1.1 and move them both into the same bin. The work-around in this code to that is to take the inputs and nudge them slightly larger, to the next available floating point number, s that if they would have been an exact match, they are now in the next category, and then to back down by 1, exactly like in your code.
This code is vectorized, in contrast to your existing code. The problem with your existing code is that it was not vectorized but was being asked to handle vectors of values.

8 Commenti

Thanks for your quick reply.
If I use +1 instead of -1 in your code everything works fine.
Otherwise, I logically get an error message regarding the index, because at the beginning 0 is the next limit and therefore 1 is generated as index. By subtracting 1, I would therefore retrieve the value of value(0) in my test function. This is not possible with MATLAB.
However, an index problem arises again if I choose x=0:0.001:8.
(So i have only changed the start value from 1 to 0.)
I can't explain this right now.
Could you help me again in this regard?
Ah, I forgot that 0*(1+eps) is 0, not eps(0). So where I wrote time*(1+eps) it should be time + eps(time)
What you say is true, but it does not solve my real problem.
I have only now really understood the function "interp1".
It compares related to this example the variable "time" with the indices of the "boundary" vector and then outputs the right limit value or by the modification the index of the left limit value.
But I need an "interval" function which compares the passed variable "time" with the values of the "boundary" vector and not with its indices. The output should then be the index of the lower/left bound of the interval and not the value of the lower bound.
This is what I tried to program at the beginning. Do you know of such a function?
As written in my main question, this example is a minimal example, because the actual function is complex.
Apparently this was badly chosen, please excuse this.
Leon Budermüller
Leon Budermüller il 5 Feb 2021
Modificato: Leon Budermüller il 5 Feb 2021
Perhaps another example to the just written.
For boundary =[b0 b1 b2 b3 b4] with b0,b1,b2,... unknown constants but b2 <= 1.7 < b3.
interp1(boundary, 1.7, 'next') = b1, because 1.7 is rounded up to 2, so the output is boundary(2).
I need unknown(boundary, 1.7, 'next') = 3, because b2 = boundary(3).
where unknown is the function I am looking for.
I hope this makes it a little clearer what I am searching for.
For this set of boundaries:
boundary = 1.5:5.5
boundary = 1×5
1.5000 2.5000 3.5000 4.5000 5.5000
Do you want the right endpoint of the boundary that contains the data?
interp1(boundary, 1.7, 'next')
ans = 2.5000
Or do you want the index of that endpoint?
interp1(boundary, 1:numel(boundary), 1.7, 'next')
ans = 2
You can process a whole data set at once:
x = 1.5+(5.5-1.5)*rand(10, 1);
y = interp1(boundary, 1:numel(boundary), x, 'next');
You could discretize the data, though the bin numbers returned by discretize are the number of the bin that contains the data, not the index of the right edge of that bin. So it differs by 1 from the output of interp1.
value = discretize(x, boundary);
results = table(x, y, value, ...
'VariableNames', {'Original Data', 'Interpolated Data', 'Bin Number'})
results = 10x3 table
Original Data Interpolated Data Bin Number _____________ _________________ __________ 1.9247 2 1 2.1311 2 1 4.001 4 3 1.8732 2 1 3.2679 3 2 4.0717 4 3 5.1058 5 4 2.4549 2 1 4.5467 5 4 4.7309 5 4
Many thanks for your help!
int = interp1(boundary, 1:numel(boundary), time, 'next')
is almost exactly what I am looking for.
The values are compared and I get the index shown.
However, there is still one small flaw:
If the following applies
boundary = [0 0.25 0.5 0.75 1 1.25 1.5 1.75 2]
then
for time = 0 it follows, that int = 1
for time = 0.000001 to time = 0.25 it follows, that int = 2
...
for time = 1.000001 to time = 1.25 it follows, that int = 6
for time = 1.250001 to time = 1.5 it follows, that int = 7
for time = 1.500001 to time = 1.75 it follows, that int = 8
for time = 1.750001 to time = 2 it follows, that int = 9
I am looking for a function that returns the left boundary instead of the right boundary of an interval such that
for time = 0 to time = 0.249999999 it follows, that int = 1
for time = 0.25 to time 0.499999999 it follows, that int = 2
...
for time = 1.25 to time = 1.49999999 it follows, that int = 6
for time = 1.5 to time = 1.74999999 it follows, that int = 7
for time = 1.75 to time = 1.99999999 it follows, that int = 8
for time = 2 it follows, that int = 9
How can I do that?
boundary = [0,0.25,0.5,0.75,1,1.25,1.5,1.75,2];
time = [0,0.249999999,0.25];
int = interp1(boundary, 1:numel(boundary), time, 'previous')
int = 1×3
1 1 2
That's it, great!
Thanks again to all of you for your time and effort.

Accedi per commentare.

Categorie

Prodotti

Release

R2018b

Community Treasure Hunt

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

Start Hunting!

Translated by