user1362166
user1362166

Reputation:

Matlab using interp1 to find the index?

I have an array of Fa which contains values I found from a function. Is there a way to use interp1 function in Matlab to find the index at which a specific value occurs? I have found tutorials for interp1 which I can find a specific value in the array using interp1 by knowing the corresponding index value.

Example from http://www.mathworks.com/help/matlab/ref/interp1.html:

Here are two vectors representing the census years from 1900 to 1990 and the corresponding United States population in millions of people.

t = 1900:10:1990;
p = [75.995  91.972  105.711  123.203  131.669...
    150.697  179.323  203.212  226.505  249.633];

The expression interp1(t,p,1975) interpolates within the census data to estimate the population in 1975. The result is

ans =
    214.8585

- but I want to find the t value for 214.8585.

Upvotes: 3

Views: 3361

Answers (5)

Roy
Roy

Reputation: 11

Andrey's solution works in principle, but the code presented here does not. The problem is with the definition of the segments, which yields a vector of 0's and 1's, whereafter the call to "t(segments(i))" results in an error (I tried to copy & paste the code - I hope I did not fail in that simple task).

I made a small change to the definition of the segments. It might be done more elegantly. Here it is:

t = 1900:10:1990;
p = [75.995  91.972  105.711  123.203  131.669...
    150.697  179.323  70.212  226.505  249.633];

val = 140;    
figure;plot(t,p,'.-');hold on;
plot( [min(t),max(t)], [val val],'r');

p1 = p - val;

tn = 1:length(t);
segments = tn([abs(diff(sign(p1)==1)) 0].*tn>0);

for i=1:numel(segments)
    x(1) = t(segments(i));
    x(2) = t(segments(i)+1);
    y(1) = p1(segments(i));
    y(2) = p1(segments(i)+1);
    m = (y(2)-y(1))/(x(2)-x(1));
    n = y(2) - m * x(2);
    index = -n/m;
    scatter(index, val ,'g');
end

Upvotes: 1

Cyrgo
Cyrgo

Reputation: 31

The answer to the most general case was given above by Andrey, and I agree with it. For the example that you stated, a simple particular solution would be:

interp1(p,t,214.8585)

In this case you are solving for the year when a given population is known.

This approach will NOT work when there is more than one solution. If you try this with Andrey's values you will only get the first solution to the problem.

Upvotes: 0

Andrey Rubshtein
Andrey Rubshtein

Reputation: 20915

In some sense, you want to find roots of a function -

f(x)-val

First of all, there might be several answers. Second, since the function is piecewise linear, you can check each segment by solving the relevant linear equation.

For example, suppose that you have this data:

t = 1900:10:1990;
p = [75.995  91.972  105.711  123.203  131.669...
    150.697  179.323  70.212  226.505  249.633];

And you want to find the value 140

val = 140;    
figure;plot(t,p);hold on;
plot( [min(t),max(t)], [val val],'r');

enter image description here

You should first subtract the value of val from p,

p1 = p - val;

Now you want only the segments in which p1 sign changes, either from + -> -, or vice versa.

segments = abs(diff(sign(p1)==1));

In each of these segments, you can solve the relevant linear equation a*x+b==0, and find the root. That is the index of your value.

for i=1:numel(segments)
    x(1) = t(segments(i));
    x(2) = t(segments(i)+1);
    y(1) = p1(segments(i));
    y(2) = p1(segments(i)+1);
    m = (y(2)-y(1))/(x(2)-x(1));
    n = y(2) - m * x(2);
    index = -n/m;
    scatter(index, val ,'g');
end

And here is the result:

enter image description here

Upvotes: 2

Dan
Dan

Reputation: 45741

interpolate the entire function to a higher precision. Then search.

t = 1900:10:1990;
p = [75.995  91.972  105.711  123.203  131.669...
    150.697  179.323  203.212  226.505  249.633];

precision = 0.5;
ti = 1900:precision:1990;

pi = interp1(t,p,ti);

now pi holds all pi values for every half a year. Assuming the values always increase you could find the year by max(ti(pi < x)) where x = 214.8585. Here pi < x creates a logical vector used to filter ti to only provide the years when p is less than x. max() is then used to take the most recent year, which will also be closest to x if the assumption that p is always increasing holds.

Upvotes: 0

angainor
angainor

Reputation: 11810

You can search for the value in Fa directly:

idx = Fa==value_to_find;

To find the index use find function:

find(Fa==value_to_find);

Of course, this works only if the value_to_find is present in Fa. But as I understand it, this is what you want. You do not need interp for that.

If on the other hand the value might not be present in Fa, but Fa is sorted, you can search for values larger than value_to_find and take the first such index:

find(Fa>=value_to_find,1);

If your problem is more complicated than that, look at Andreys answer.

Upvotes: 1

Related Questions