Filter data into different Phases using multiple conditions.

4 Ansichten (letzte 30 Tage)
Daan
Daan am 23 Sep. 2015
Bearbeitet: arich82 am 25 Sep. 2015
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

Akzeptierte Antwort

arich82
arich82 am 23 Sep. 2015
Bearbeitet: arich82 am 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.
  7 Kommentare
Daan
Daan am 25 Sep. 2015
Thank you so much. There is one typo in your last script (nposts = 3 should be nspots = 3). But it works great! Thank you for all the help!
arich82
arich82 am 25 Sep. 2015
I corrected the typo.
I'm glad it helps.
I still might play around with it over the weekend...

Melden Sie sich an, um zu kommentieren.

Weitere Antworten (1)

Thorsten
Thorsten am 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;
  3 Kommentare
Thorsten
Thorsten am 24 Sep. 2015
i = 1;
while numel(C) > 1
%insert algorithm from above
phase1{i} = C(i1:i2);
i = i + 1;
if i2 == numel(C), C = []; else, C = C(i2+1:end); end
end
Daan
Daan am 24 Sep. 2015
Thanks for helping me. The following script gives me the error but I can't figure out what is the problem?
??? Cell contents assignment to a non-cell array object.
Error in ==> DetermineMeansRecoveryPushFase at 112 phase1{i} = C(i1:i2);*
while numel(C) > 1
ind = find(C> 1) + 3;
ind = ind(ind < numel(C));
i1 = ind(find(C(ind) > 3, 1, 'first'));
ind2 = find(C < 1);
i2 = ind2(find(ind2 - i1 > 0, 1, 'first'));
phase1 = zeros(size(C));
phase1(i1:i2) = 1;
phase1{i} = C(i1:i2);
i = i + 1;
if i2 == numel(C), C = []; else, C = C(i2+1:end); end
end

Melden Sie sich an, um zu kommentieren.

Produkte

Community Treasure Hunt

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

Start Hunting!

Translated by