A second basic 'Find' question

1 次查看(过去 30 天)
I want to identify starting point of a range of values whereby the first value is greater than or equal to X and all subsequent values are greater than another value (Y), which smaller than X. The exact length of the range isn't known exactly (it has at least N points) no other data range of similar length or longer occurs within the data set.
For example: 1, 2, 3, 4, 5,6,3.5,3.1, 7,6,8,6,5,3,1,2,3,4, X=4 Y=3 N=5 I want to find the range which starts greater than or equal to 4 and doesn't fall below 3. I know that there are at least 5 data points within the range of interest.

采纳的回答

Matt Fig
Matt Fig 2011-6-15
idx = findstr([0 data>=X],[0 1]);
idx = idx(ismembc(idx,findstr(data>Y,ones(1,N))))
  3 个评论
Andrew Newell
Andrew Newell 2011-6-16
Matt - interesting use of findstr, and quite fast!
Etienne O'Brien
Etienne O'Brien 2011-6-16
Thank you Matt for this answer and others for contributing.

请先登录,再进行评论。

更多回答(2 个)

Andrew Newell
Andrew Newell 2011-6-14
My initial response was not very robust, so I have completely rewritten it:
data = data(:);
% Find how many adjacent terms are > Y
I = data>Y;
I = conv(double(I),ones(N,1));
I = I(N:end);
% Select elements > X and return length of sequence
I = I.*(data>=X);
% See if any sequences are long enough and display results
i1 = find(I>=N,1,'first');
if any(i1)
i2 = i1+I(i1)-1;
disp(['Index range = ',num2str(i1),':',num2str(i2)])
disp(['Selected data = ',num2str(data(i1:i2)')])
else
disp('No sequence found.')
end

Andrei Bobrov
Andrei Bobrov 2011-6-14
I1 = find(data == X,1);
X1 = data(I1:end) > Y;
xf = find([true diff(X1)~=0]);
idx = [xf; xf(2:end)-1 length(X1)];
idx(:,X1(idx(1,:))==0)=[];
idx1 = idx + I1 -1;
[non,I] = max(diff(idx1));
out = data(idx1(1,I):idx1(2,I));
MORE
idx = bsxfun(@plus,1:(N+1),(0:length(data)-N-1)');
ii = find(data==X,1);
id = idx(ii:end,:);
I = find(all(data(id) > Y,2));
out = data(id(I(1)):id(I(end)+N))
EDIT after comments of Andrew Newell. Very much thanks Andrew!
idx = bsxfun(@plus,1:(N+1),(0:length(data)-N-1)');
ii = find(data>=X,1);
id = idx(ii:end,:);
I = find(any(data(id) > Y,2));
out = data(id(I(1)):id(I(end)));
MORE variant (after last comments of Andrew Newell)
data = data(:);
dg3 = data > Y;
dge4 = data >= X;
xstrts = [true; diff(dge4)~=0]&dge4;
yends = flipud([true; diff(flipud(dg3))~=0])&dg3;
ii = [find(xstrts) find(yends) ];
out = cell2mat(arrayfun(@(x)data(ii(x,1):ii(x,2))',1:size(ii,1),'un',0));
  2 个评论
Andrew Newell
Andrew Newell 2011-6-15
Try this test example:
data = rand(1,10000); data(101:105)=[4.1 3.3 3.3 3.3 3.3];
X=4; Y=3; N=5;
Andrew Newell
Andrew Newell 2011-6-15
You're welcome! Here's another:
data = rand(1,1000); data(101:105)=[4.1 3.3 3.3 3.3 3.3]; data(1:4) = [4.1 3.3 3.3 3.3];
X=4; Y=3; N=5;

请先登录,再进行评论。

标签

Community Treasure Hunt

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

Start Hunting!

Translated by