MATLAB中怎样找出一维向量的急剧变化点?
比如a=[1,2,3,2.5,4,10,13,17,20,23],想在10这个地方断开,并给出10在向量a中的位置,怎么实现?
实际上,我这里的向量a不止有一个拐点,给一个更具体的例子吧:
a=[1 2 2.5 3.2 5 5.1 5 5.2 5 5.3 5.2 7 11 16 17],这里的a在数值5附近基本保持不变,现在需要找出这个水平段的拐点,有什么比较简单的办法吗?
clear
clc
a=[1 2 2.5 3.2 5 5.1 5 5.2 5 5.3 5.2 7 11 16 17];
n=length(a);
Ia=1:n;
pa=spline(Ia,a);
m=2;% 分成三段
Iam0=linspace(1,n,m+2);
Iam0=Iam0(2:end-1);
% fmincon 用的约束条件,但是这个函数有警告
% A=diag(ones(1,m),-1)+diag(-ones(1,m+1));A(:,end)=[];
% b=[-1;zeros(m-1,1);n];
Iam=fminsearch(@(x)sum(abs(interp1([1,x,n],ppval(pa,[1,x,n]),Ia,'linear')-a)),Iam0);%,A,b
Iam=[1,round(Iam),n];
plot(Ia,a,'*')
hold on
plot(Iam,a(Iam),'-r')
谢谢啦。我只是想找到离散曲线的两个拐弯点即可,并不需要曲线拟合,你是人为地将a分成了3段了吧?
谢谢你这么细致地为我指点。我实际上只需要确定出a代表曲线的水平段的起始位置即可。
追答对呀,变量Iam(1 x m, m=2)就是两个拐点的下标,以Iam为变量,拐点分开的三段(m+1)直线与曲线的绝对误差和为目标,找到最佳变量,即拐点。根据拐点的多少m也可以取其它整数值。
追问谢谢啦,会给你好评啊。我想进一步知道,如果a中有2个甚至更多个水平折线,你这种找水平段的方法还适用不?要是管用的话,这真是一个绝佳办法!
刚补充的这个问题的关键点是,预先不知道到底有几个水平折线(2个,3个,4个都有可能),只需找到长度最长的那个水平折线即可!
追答适合多个的情况,但个数只能人工控制,而且越多,计算复杂度也越高一些。如果只需“找到长度最长的那个水平折线”,这不是最佳方式,试试下面的方法:
clear
clc
a=[1 2 2.5 3.2 5 5.1 5 5.2 5 5.3 5.2 7 11 16 17 17+[5.1 5 5.2 5 5.3]];
n=length(a);
tol=0.5;% tol 为寻找水平点时,容许的数据误差
da=[abs(diff(a))<tol,0];% |差分|
j1=0;j2=0;s1=0;s2=0;
for i=1:n
if da(i)==0
if s2<s1
s2=s1;%s2 最长水平段的数据个数-1
j2=j1;%j2 最长水平段的起始下标
end
s1=0;j1=0;
else
if j1==0
j1=i;%j1 水平段的起始下标
end
s1=s1+1;%s1 水平段的数据个数-1
end
end
plot(a,'b*')
hold on
plot(j2:(j2+s2),a(j2:(j2+s2)),'-r')
谢谢啦!
本回答被提问者采纳