2

In Matlab I have a vectors that looks like this:

0 0 1 1 0 0 0 1 1 0 0 0 0 1 1 1 0 0 0 0 1 0 1

What I want to do now is to count the number of 1 in this vector. Consecutive 1s count as 1. Additionally, I want also to calculate the average and median numbers of 0s between 1s. So for this example:

1s: 5

Median 0s: 3.5

Average 0s: 3

I solved that with a brute force method, that is investigate each element in a loop and check the previous as well as the next element. But I'm sure there has to be a solution that is way faster. Any idea?

RoflcoptrException
  • 51,941
  • 35
  • 152
  • 200
  • Could you please tell how average & median is calculated here of zeros ? I've a solution for consecutive 1's – P0W Sep 08 '13 at 13:21
  • Counting the ones should work like this: vector*[1;1-vector(1:end-1)']. Maybe the vector has to be casted to "double" if it is boolean. Unfortunately this would not solve the problem with the average number of zeroes in between. – Martin Rosenau Sep 08 '13 at 13:23
  • @P0W There are 3 times 0s after the first 1, then 4 times 0s after the next block of consecutive 1s, then 4 and then 1. So i calculate the mean and median of the sequence 3 4 4 1. – RoflcoptrException Sep 08 '13 at 13:28
  • @ElianT Count only zeros _between_ ones – Luis Mendo Sep 08 '13 at 14:56
  • possible duplicate of [Count the occurrence of consecutive 1s in 0-1 data in MATLAB](http://stackoverflow.com/questions/6330588/count-the-occurrence-of-consecutive-1s-in-0-1-data-in-matlab). Also possibly related: [Run Length Encoding in Matlab](http://stackoverflow.com/questions/12059744/run-length-encoding-in-matlab) – Eitan T Sep 08 '13 at 15:03

3 Answers3

4

Given the data in vector v,

v = [ 0 0 1 1 0 0 0 1 1 0 0 0 0 1 1 1 0 0 0 0 1 0 1 ]; % data

compute as follows:

w = [ 1 v 1 ]; % auxiliary vector
runs_zeros = find(diff(w)==1)-find(diff(w)==-1); % lenghts of runs of 0's

% Desired results:
number_ones = length(runs_zeros)-1+v(1)+v(end);
% For average and median, don't count first run if v(1) is 0,
% or last run if v(end) is 0:
average_runs_zeros = mean(runs_zeros(2-v(1):end-1+v(end))); 
median_runs_zeros = median(runs_zeros(2-v(1):end-1+v(end)));

This is faster than @TryHard's solution because it doesn't require converting to strings

Luis Mendo
  • 110,752
  • 13
  • 76
  • 147
1

Okay, so this seems to be working

>> a=[0 0 1 1 0 0 0 1 1 0 0 0 0 1 1 1 0 0 0 0 1 0 1];
>> %Remove traling and leading zeros
>> y = a(find(a,1,'first'):find(a,1,'last'));
>> q = diff([0 a 0] == 1);
>> v = find(q == -1) - find(q == 1);
>> length(v) % Consecutive Ones
ans =

     5

>> q = diff([0 ~y 0] == 1);
>> v = find(q == -1) - find(q == 1);
>> v

v =

     3     4     4     1

>> median(v)

ans =

    3.5000

>> mean(v)

ans =

    3
P0W
  • 46,614
  • 9
  • 72
  • 119
0

You can do it as follows:

dat=[0 0 1 1 0 0 0 1 1 0 0 0 0 1 1 1 0 0 0 0 1 0 1];
str = regexprep(num2str(dat),' ','');
[n1 istart1 iend1] = regexp(str,'[1]+','match','start','end');
[n0 istart0 iend0] = regexp(str(min(istart1):max(iend1)),'[0]+','match','start','end');

% number of strings of `1`s
length(n1)

% property of intercalated strings of `0`s
median([iend0-istart0+1])
mean([iend0-istart0+1])
Buck Thorn
  • 5,024
  • 2
  • 17
  • 27