average of range of values in a matrix
5 views (last 30 days)
Show older comments
Hello,
I have a matrix d (NxN), which looks like that:
Can I use a for loop to say, calculate the average value of all lines in column 1, which have the same value in column 3?
n = amount of same values (here 3 x 11)
and give me a vektor which looks like that:
Can I tell the for loop to find automatically all multiple values in column 3? Like now it's 11, 16, 21, but maybe the next matrix has in column 3 10, 12, 14,...
0 Comments
Answers (3)
dpb
on 13 Nov 2015
Edited: dpb
on 13 Nov 2015
[u,~,ib]=unique(x(:,3)); % get the unique values and locations for each
val=x(:,1:2); % shorthand for the subset over which to average
mx(:,3)=u; % preallocate for the result array & assign index values
for i=1:2 % for the two columns
mx(:,i)=accumarray(ib,val(:,i),[],@mean); % compute the mean over the subsets
end
Seems like should be able to do it w/o the loop over the columns but I drew a blank at the moment as to how to since accumarray val argument must be a vector
2 Comments
Image Analyst
on 13 Nov 2015
Yeah, I thought of accumarray too, but accumarray is such a mind-bender I have to research it in the help every time because it's kind of complicated, so sometimes I just do the brute force but intuitive approach. However, I'm sure Andrei Bobrov, master of the one-liners, will come along shortly and do the whole thing in one compact but totally cryptic and impenetrable line of code.
dpb
on 13 Nov 2015
Yeah, Andrei's the guru there, fur shur... :) I agree w/ accumarray; it's capable but complex-enough to always take a couple of tries and if it's been a while since last foray.
I realize I forgot to add the OP's last wish above; namely to include the value of the indexing variable as the last column...
Could change a little; start with
mx(:,3)=u;
for the preallocation and setting the values together...
Fabi Boro
on 14 Nov 2015
1 Comment
dpb
on 14 Nov 2015
x is a placeholder for your original variable--you don't say what you've named the...well, in looking again I see that I did overlook that in, sorry--use 'd' in place of 'x'.
mx stands for "mean of x" for the result; use whatever you want instead, of course.
The difference between the two solutions is that the first leaves you with a 2-column result of the two means; the latter finishes the job by storing the unique indices vector of the groups as the third column per the original request. Matlab automagically allocates full memory to the largest subscript dimension in an assignment of this kind; try, say,
newvar(3,3)=pi
at the command line to see how the assignment to a single location serves the same function as
newvar=zeros(3);
newvar(3,3)=pi;
it simply saves a step.
Andrei Bobrov
on 18 Apr 2016
Hi friends! In four rows
A = [1234 785 11
5678 457 11
9101 390 11
2467 381 16
3573 737 16
2354 938 16
8467 729 21
3477 900 21];
[a,~,c] = unique(A(:,3));
[x,y] = ndgrid(c,1:2);
A1 = A(:,1:2);
out = [accumarray([x(:),y(:)],A1(:),[],@mean),a];
0 Comments
See Also
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!