Reputation: 49
I have a matrix:
V1 V2
1 12
1 12
0 23
0 24
1 45
1 67
I want to calculate the mean of the successive values of V2 only as long as V1 is >0 and insert the results into a new matrix. I want to do this for all values of V1. In this example I would get:
12
56
Any idea how I can do this in Matlab? Thank you.
Upvotes: 1
Views: 52
Reputation: 19689
Using the idea of manipulating V1
and creating subs
from rahnema1's answer, here is an alternative way of using accumarray
:
V1 = V1 > 0;
subs = cumsum(diff([false;V1]) == 1);
result = accumarray (subs(V1), V2(V1), [], @mean);
Benchmark:
Here is a comparison of the two answers:
V1 = repmat(V1,1e6,1);
V2 = repmat(V2,1e6,1);
V1 = V1 > 0;
subs = cumsum(diff([false;V1]) == 1);
disp(['rahnema1''s answer = ', num2str(timeit(@() rahnema1(V1,V2,subs)))]);
disp(['Usama''s answer = ', num2str(timeit(@() usama(V1,V2,subs)))]);
function rahnema1(V1,V2,subs)
p = V1 .* V2;
f = find(V1,1);
result = accumarray (subs(f:end), f:numel(V1), [], @(x)sum(p(x))./sum(V1(x)));
end
function usama(V1,V2,subs)
result = accumarray (subs(V1),V2(V1), [], @mean);
end
rahnema1's answer = 4.3385
Usama's answer = 5.6088
⇒ rahnema1's code is faster than that of mine.
Upvotes: 2
Reputation: 15867
Here is a solution using cumsum
and accumarray
:
V1 = V1 > 0;
f = find(V1,1);
subs = cumsum(diff([false;V1]) == 1);
p = V1 .* V2;
result = accumarray ( ...
subs(f:end), ...
f:numel(V1), ...
[], ...
@(x)sum(p(x))./sum(V1(x))...
);
Upvotes: 2