'For loop to average over individual time points Matlab
I have a 21x2 vector in Matlab that looks like this:
A = [0.5 0.6 0.7 0.8 0.9 1.0 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 2.0 2.1 2.2 2.3 2.4 2.5;
0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1]';
each element in the first row corresponds to either a 0
or 1
in the second row. I need to treat each of the set of 0's
and 1's
as blocks so that I can single out the elements such that I have a vector containing all the first elements of the 1
blocks and then another vector containing all the second elements of the 1
blocks and so on until I have all the elements separated out.
so for e.g. vector1=[1.0 2.1]
, vector2=[1.1 2.2]
etc etc.
This is because I need to average over individual points between blocks so that I have for e.g. avg_vector1, avg_vector2, avg_vector3... etc.
So far I have been trying to write a loop to do this but I can already tell it won't be so efficient and might not work every time because I will have to have a an if
for each j
(see below) and the "number of j's" is not really fixed, sometimes the block could be longer, sometimes it could be shorter.
j=1;
for i=1:size(A,1)
if A(i,2)==1
if j==1
vector1(i)=A(i,1);
j=j+1; %j is acting as a counter for the "size" of the block of 0's and 1's
if j==2
vector2(i)=A(i,1);
**incomplete**
Does anyone know how to do this more elegantly and simply?
Thanks
Solution 1:[1]
(Hopefully) correct version:
M = logical(A(:, 2));
is_start = [M(1); ~M(1:end-1) & M(2:end)];
is_start = is_start(M);
A_valid = A(M, 1);
group_idx = cumsum(is_start);
group_start_idx = find(is_start);
sub_idx = (1:numel(is_start))' - group_start_idx(group_idx)+1;
means = accumarray(sub_idx, A_valid, [], @mean);
There is possibly a slightly neater way of doing this with one or two fewer steps, but this should work.
Take home lesson: use cumsum
more often!
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | General Grievance |