Matlab使用interp1函数如何找到索引?

3
我有一个包含从函数中获取的值的Fa数组。是否有办法在Matlab中使用interp1函数找到特定值出现的索引?我已经找到了使用interp1的教程,可以通过知道对应的索引值使用interp1在数组中找到特定值。
来自http://www.mathworks.com/help/matlab/ref/interp1.html的示例:
这里有两个向量,表示1900年至1990年的人口普查年份和相应的美国人口(以百万人计)。
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];

该表达式 interp1(t,p,1975) 在人口普查数据内插值,以估计1975年的人口数量。结果为:
ans =
    214.8585

- 但我想找到 214.8585t 值。


你为什么要使用 interp - angainor
我想使用interp1来找到产生215的t值,至少这是我尝试编写代码的一部分的理解。还有其他方法可以做到吗? - user1362166
5个回答

2
在某种意义上,您想要找到函数的根 -
f(x)-val
首先,可能会有几个答案。其次,由于函数是分段线性的,您可以通过解决相关的线性方程来检查每个线段。
例如,假设您有以下数据:
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];

而且你想找到值为140的内容

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

enter image description here

你应该先从 p 中减去 val 的值,

p1 = p - val;

现在你只想要那些 p1 符号发生变化的片段,无论是从 +-,还是反过来。

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

在每个片段中,您可以解决相关的线性方程a*x+b==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

这里是结果:

enter image description here


我猜我们对这个问题的理解有点不同 ;) - angainor

1
Andrey的解决方案原则上是可行的,但这里呈现的代码不行。问题在于段的定义,它产生了一个由0和1组成的向量,之后调用“t(segments(i))”会导致错误(我尝试复制并粘贴代码-希望我没有在这个简单的任务中失败)。
我对段的定义进行了小改动,可能可以更优雅地完成。这就是它:
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

1

您可以直接在Fa中搜索该值:

idx = Fa==value_to_find;

要查找索引,请使用find函数:
find(Fa==value_to_find);

当然,这仅在value_to_find存在于Fa中时才有效。但据我所知,这正是您想要的。您不需要interp来实现这一点。

另一方面,如果值可能不存在于Fa中,但Fa已排序,则可以搜索大于value_to_find的值并取第一个索引:

find(Fa>=value_to_find,1);

如果你的问题比这个更复杂,请看安德烈的回答。


0

将整个函数插值到更高的精度,然后搜索。

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);

现在pi包含每半年的所有pi值。假设这些值总是增加的,你可以通过max(ti(pi < x))找到年份,其中x = 214.8585。这里pi < x创建了一个逻辑向量,用于过滤ti,只提供p小于x时的年份。然后使用max()来获取最近的年份,如果假设p始终增加成立,则该年份也将最接近x。


顺便提一下,pi 是一个糟糕的变量名,因为它会覆盖 Matlab 内置的 pi 常量。所以请使用其他名称。 - Dan

0

最一般情况的答案已经由Andrey给出,我也同意他的观点。 对于你提出的例子,一个简单的特殊解决方案是:

interp1(p,t,214.8585)

在这种情况下,您正在解决已知人口时的年份。
当存在多个解决方案时,此方法将无法使用。如果您尝试使用安德烈的值进行此操作,则只会得到问题的第一个解决方案。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接