A second basic 'Find' question

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.

 Akzeptierte Antwort

Matt Fig
Matt Fig am 15 Jun. 2011

1 Stimme

idx = findstr([0 data>=X],[0 1]);
idx = idx(ismembc(idx,findstr(data>Y,ones(1,N))))

3 Kommentare

Andrei Bobrov
Andrei Bobrov am 15 Jun. 2011
Hi Matt! Your method is very good!
We have:
idx = [strfind(([0 data>X]),[0 1]);strfind(data<Y,[0 1])];
out = cell2mat(arrayfun(@(x)data(idx(1,x):idx(2,x)),1:size(idx,2),'un',0))
Andrew Newell
Andrew Newell am 16 Jun. 2011
Matt - interesting use of findstr, and quite fast!
Etienne O'Brien
Etienne O'Brien am 16 Jun. 2011
Thank you Matt for this answer and others for contributing.

Melden Sie sich an, um zu kommentieren.

Weitere Antworten (2)

Andrew Newell
Andrew Newell am 14 Jun. 2011

0 Stimmen

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

2 Kommentare

Matt Fig
Matt Fig am 15 Jun. 2011
I = I.*(data>=X);
Andrew Newell
Andrew Newell am 15 Jun. 2011
Thanks for noticing that!

Melden Sie sich an, um zu kommentieren.

Andrei Bobrov
Andrei Bobrov am 14 Jun. 2011

0 Stimmen

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 Kommentare

Andrew Newell
Andrew Newell am 15 Jun. 2011
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 am 15 Jun. 2011
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;

Melden Sie sich an, um zu kommentieren.

Kategorien

Mehr zu MATLAB finden Sie in Hilfe-Center und File Exchange

Tags

Community Treasure Hunt

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

Start Hunting!

Translated by