Azzera filtri
Azzera filtri

A second basic 'Find' question

1 visualizzazione (ultimi 30 giorni)
Etienne O'Brien
Etienne O'Brien il 14 Giu 2011
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.

Risposta accettata

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

Accedi per commentare.

Più risposte (2)

Andrew Newell
Andrew Newell il 14 Giu 2011
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 Commenti
Matt Fig
Matt Fig il 15 Giu 2011
I = I.*(data>=X);
Andrew Newell
Andrew Newell il 15 Giu 2011
Thanks for noticing that!

Accedi per commentare.


Andrei Bobrov
Andrei Bobrov il 14 Giu 2011
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 Commenti
Andrew Newell
Andrew Newell il 15 Giu 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 il 15 Giu 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;

Accedi per commentare.

Tag

Community Treasure Hunt

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

Start Hunting!

Translated by