Finding durations between 1's in a matrix

1 view (last 30 days)
I am creating a matrix of ones
I = binornd(1,a,T(j),n);
What i need to find next is the durations between the 1 values for each column, that is to say that for each column i will need a vector with the durations between values of 1 in the columns of the matrix.
the duration is simply the difference between the occurences, so for example if there is a 1 in (1,1) of the matrix and (3,1). Then the first number in the duration vector would be 3-1=2
Thanks! I am trying to avoid doing a for loop on this (in part because i want to get better at avoiding them in general!)
  4 Comments
Image Analyst
Image Analyst on 27 Mar 2013
Edited: Image Analyst on 27 Mar 2013
Please give the expected output for the above matrix. Say for columns 5, so you want a column vector [1;2;1;1] that is the length of all runs of zeros, or do you want the average length of a run which would be (1+2+1+1)/4 = 1.25? If you want a list of all runs for each column, then the list may have different numbers of runs for each column and then you could either use a cell array, or a regular array with some wasted space - not sure which you think would be easier.
Also, do you have the Image Processing Toolbox, which might make this easier.
By the way, I wouldn't worry about loops for microscopic arrays like this. If you have millions of elements then it might start to become a factor.
DoVile Last Name:
DoVile Last Name: on 27 Mar 2013
For col 5 the durations are
[1 2 3 2 2]
i guess my goal would be a cell array of such vectors. I do have access to the image processing toolbox.
You are completely right, i just would prefer some nice looking and fast code as i need it for simulation study and my thesis. SO it needs to be fast and look as nice as i can make it look, in case someone actually took a look at it :)

Sign in to comment.

Accepted Answer

DoVile Last Name:
DoVile Last Name: on 27 Mar 2013
Edited: DoVile Last Name: on 27 Mar 2013
In the end i decided on just using a double for loop with an if statement, if anyone comes up with something elegant that would be great too. In case any one finds the post later on here is the code
for k=1:n
dcounter = 1;
for l=1:T(j)
if I(l,k)==1;
tempd(dcounter) = l;
dcounter=dcounter+1;
end
end
d{k} = diff(tempd);
end
Thank you for your time guys :)

More Answers (1)

Cedric
Cedric on 27 Mar 2013
Edited: Cedric on 27 Mar 2013
If you had the following matrix I for example:
>> I = rand(10,5) > 0.6
I =
0 1 1 0 0
0 1 0 0 1
1 0 1 0 0
0 0 0 0 0
1 0 0 1 1
0 0 1 0 1
0 0 1 0 0
1 0 0 0 0
1 1 1 0 0
0 1 0 0 0
you could get a 'per column' statistics of the duration/rowID difference between consecutive non-zero elements, as follows:
>> stat = arrayfun(@(cId) prctile(diff(find(I(:,cId))).', [25,50,75]), ...
1:size(I,2), 'UniformOutput', false)
stat =
[1x3 double] [1x3 double] [1x3 double] [1x3 double] [1x3 double]
where
>> stat{1}
ans =
1.2500 2.0000 2.7500
for example is a vector containing the 25th, 50th, and 75th percentile of "duration" differences for column 1.
The idea here can be illustrated with column 1 for example: the following
>> find(I(:,1))
ans =
3
5
8
9
provides you with row IDs of non-zero elements (durations in your context). You can then compute differences between consecutive elements:
>> diff(find(I(:,1)))
ans =
2
3
1
and make a stat of these for example:
>> prctile(diff(find(I(:,1))), [25,50,75])
ans =
1.2500 2.0000 2.7500
you could have taken the mean/min/max as well.
Now ARRAYFUN repeats this for all column IDs and outputs one vector of stats (resulting from PRCTILE) per column ID in a cell array.

Products

Community Treasure Hunt

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

Start Hunting!