2 views (last 30 days)

Show older comments

Hi all,

I have got data which looks like C=[0,3 0,8 0,3 1,3 0,6 1,1 3,1 5,1 3,1 0,5]. I want to split this data into 2 Phases. Phase 1 will start when >1 (condition1) AND 3 spots after this point it must be > 3(condition2). Phase 1 will end when <1. D should eventually look like [0 0 0 0 0 1 1 1 1 0].

Condition 1 can easily be tested by D=C>1. But I can't figure out how to expand the filter by condition 2? How can I achieve this?

Many Thanks, Daan

arich82
on 23 Sep 2015

Edited: arich82
on 24 Sep 2015

I think you can achieve this by a variation on run length encoding. First, encode the data based on condition 1, then use condition 2 to modify the decoding. (Note that I'm interpretting condition 2 to mean '**still** greater than 1' for three spots; let me know if this is correct).

% data

C=[0.3 0.8 0.3 1.3 0.6 1.1 3.1 5.1 3.1 0.5];

% make data nontrivial

C = [C, C]

% apply condition 1

L = C > 1

% get index of the start of each phase change

%

% note: the first index is always the start of the first phase, so

% we begin the mask with true

mask = [true, logical(diff(L))]

idx = find(mask)

% compute the run-length of each phase

%

% note: an 'extra' index is appended to the end of the data,

% (essentially a 'phantom' phase starting past the end of the data)

% in order to get the correct length of the last phase

rl = diff([idx, numel(C)+1])

% extract the values associated with the run-length encoding

v = L(mask)

% apply condition 2

% i.e. require all '1' phases to also have a run-length > 3

v = v & (rl > 3)

% decode the rle

D = v(cumsum(mask))

The input C and output D are (printed columnwise for easier comparison)

>> [num2str(C(:)), repmat(' ', numel(C), 1), num2str(D(:))]

ans =

0.3 0

0.8 0

0.3 0

1.3 0

0.6 0

1.1 1

3.1 1

5.1 1

3.1 1

0.5 0

0.3 0

0.8 0

0.3 0

1.3 0

0.6 0

1.1 1

3.1 1

5.1 1

3.1 1

0.5 0

Please accept this answer if it helps, or leave a note in the comments if I've missed something.

arich82
on 25 Sep 2015

I corrected the typo.

I'm glad it helps.

I still might play around with it over the weekend...

Thorsten
on 23 Sep 2015

The indices three positions after C is > 1 can be found using

ind = find(C > 1) + 3;

Ensure that the indices are not larger than the number of elements in C

ind = ind(ind < numel(C));

Start of phase 1

i1 = ind(find(C(ind) > 1, 1, 'first'))

Start of phase 2

ind2 = find(C < 1);

i2 = ind2(find(ind2 - i1 > 0, 1, 'first'));

phase1 = zeros(size(C));

phase1(i1:i2) = 1;

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

Start Hunting!