Filter data into different Phases using multiple conditions.

4 ビュー (過去 30 日間)
Daan
Daan 2015 年 9 月 23 日
編集済み: arich82 2015 年 9 月 25 日
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
arich82 2015 年 9 月 23 日
編集済み: arich82 2015 年 9 月 24 日
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 件のコメント
Daan
Daan 2015 年 9 月 25 日
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 2015 年 9 月 25 日
I corrected the typo.
I'm glad it helps.
I still might play around with it over the weekend...

サインインしてコメントする。

その他の回答 (1 件)

Thorsten
Thorsten 2015 年 9 月 23 日
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 件のコメント
Thorsten
Thorsten 2015 年 9 月 24 日
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 2015 年 9 月 24 日
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

サインインしてコメントする。

カテゴリ

Help Center および File ExchangeVisualization についてさらに検索

製品

Community Treasure Hunt

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

Start Hunting!

Translated by