function [b, n, index] = RunLength(x)
d = [true; diff(x(:)) ~= 0]; % TRUE if values change
b = x(d); % Elements without repetitions
k = find([d.', true]); % Indices of changes
n = diff(k); % Number of repetitions
index = k(1:numel(k) - 1);
if iscolumn(x)
n = n.';
index = index.';
end
end
data = [1.2;1.0;0.05;0.4;0.3;0.2;0.1;0.05;0.04;0.03;0.03;0.02;0.01;0.001;0.01;0.01;0.001 ] ;
[b, n, index] = RunLength(data < 0.1);
match = find(b & n >= 10, 1);
result = index(match)
% This function find the number of row which 10 consecutive rows from the
% this computed row are smaller than 0.10. The result equals 8th row.
I need to use this function with loop such as;
data= 605x1 array includes numeric data
I need to compute the "result" with every 121 rows within 605 rows. So I need to run RunLength function five times (to produce five different result ) using the every 121 rows of the "data". I tried the below codes but it doesn't work;
i=1:121:605
for j=5
[b(:,j), n(:,j), index(:,j)] = RunLength(abs(data(i(j))) < 0.1);
match(j) = find(b(:,j) & n(:,j) >= 10, 1);
result(j) = index(match)
end

 Accepted Answer

Jan
Jan on 26 Apr 2021
Edited: Jan on 26 Apr 2021
Result = zeros(1, 5);
iResult = 0;
for k = 1:121:605
datak = data(k:k+120);
[b, n, index] = RunLength(datak < 0.1);
match = find(b & n >= 10, 1);
iResult = iResult + 1;
Result(iResult) = index(match);
end
Maybe you have to catch the case, that match is empty.
Alternatively:
Result = zeros(1, 5);
iResult = 0;
for k = 1:5
index = (k - 1)*121 + 1;
datak = data(k:k+120);
[b, n, index] = RunLength(datak < 0.1);
match = find(b & n >= 10, 1);
Result(k) = index(match);
end

5 Comments

Dear @Jan
The first batch of codes worked well, but when match becomes empty (not satisfy the condition), the codes gives
Improper assignment with rectangular empty matrix.
The second part of the codes does not work properly, it produces Result=1 when I tried the real data. If there is a change to handle the empty match in the first part, it will work efficently. For example, if there is a predetermined value can be assign for empty "match", it will be worked well.
"If there is a change to handle the empty match in the first part, it will work efficently." - then insert this check:
if isempty(match)
Result(iResult) = NaN;
else
Result(iResult) = index(match);
end
I do not see a problem in the 2nd code.
Dear @Jan
The attached file is the original data file (53361 x 1). When using the second part of your codes as;
size_data=numel(data);
repitition=size_data/121;
Result = zeros(1, repitition);
iResult = 0;
for k = 1:121:size_data
index = (k - 1)*121 + 1;
datak = abs(data(k:k+120));
[b, n, index] = RunLength(datak < 0.1);
match = find(b & n >= 10, 1);
Result(k) = index(match);
end
It produces "Improper assignment with rectangular empty matrix." this error.
When the first part of your codes worked, two problem arises. One is the 53361/121=441 Results need to be created, whereas 377 Results are created, the other remaning Results are equal 0. The second one is, third Results are computed as NaN, whereas it should be 7 in according with the real data. I applied the first part of your code as follows;
size_data=numel(data);
repitition=size_data/121;
Result = zeros(1, repitition);
iResult = 0;
for k = 1:121:size_data
datak = abs(data(k:k+120));
[b, n, index] = RunLength(datak < 0.1);
match = find(b & n >= 20, 1);
if isempty(match)
Result(iResult) = NaN;
else
iResult = iResult + 1;
Result(iResult) = index(match);
end
end
Jan
Jan on 27 Apr 2021
Edited: Jan on 27 Apr 2021
"Improper assignment with rectangular empty matrix." - this is the already mentioned problem, when match is empty. In the 2nd code you'd need to insert the isempty(match) check also.
You need to advance iResult even if match is empty:
size_data=numel(data);
repitition=size_data/121;
Result = zeros(1, repitition);
iResult = 0;
for k = 1:121:size_data
datak = abs(data(k:k+120));
[b, n, index] = RunLength(datak < 0.1);
match = find(b & n >= 20, 1);
iResult = iResult + 1; % Before the IF ISEMPTY(match) check
if isempty(match)
Result(iResult) = NaN;
else
Result(iResult) = index(match);
end
end
Or slightly simplified:
size_data=numel(data);
repitition=size_data/121;
Result = NaN(1, repitition); % NaN as default
iResult = 0;
for k = 1:121:size_data
datak = abs(data(k:k+120));
[b, n, index] = RunLength(datak < 0.1);
match = find(b & n >= 20, 1);
iResult = iResult + 1;
if ~isempty(match)
Result(iResult) = index(match);
end
end
Dear @Jan
Thank you very much for your solution.

Sign in to comment.

More Answers (0)

Categories

Asked:

on 26 Apr 2021

Commented:

on 27 Apr 2021

Community Treasure Hunt

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

Start Hunting!