0
votes

Suppose I have the following array:

A=[1 2
   1 4
   2 6
   3 5
   5 7
   1 9
   2 7];

What is the most efficient (preferably one-liner) way in MATLAB to automatically obtain a matrix which holds the average value of the second column elements for every unique element in the first column? The result for A above would be:

B=[1 mean([2 4 9])
   2 mean([6 7])
   3 mean([5])
   5 mean([7])];

Thanks in advance!

2

2 Answers

1
votes

unique can generate the first column while the powerful accumarray equipped with the mean function will calculate the second (nonzeros is called for non-existent indices like 4 in this case):

>> B = [unique(A(:,1)),nonzeros(accumarray(A(:,1),A(:,2),[],@mean))]
B =
    1.0000    5.0000
    2.0000    6.5000
    3.0000    5.0000
    5.0000    7.0000

As noted in the comments by dan-man, the above approach only works if the first column always has integer values (I guess I implied this use-case from the given example; apologies). You can use unique to get around the shortcoming as follows:

[Aunq,~,Aind] = unique(A(:,1));
B = [Aunq,accumarray(Aind,A(:,2),[],@mean))];

Further pointed out was the fact that due to how accumarray works internally, calling mean directly is not as efficient as performing the calculation more directly:

B = [Aunq,accumarray(Aind,A(:,2),[],@sum)./accumarray(Aind,1,[],@sum)]
0
votes
B=[];for k=unique(A(:,1)).';B=[B;k sum((A(:,1)==k).*A(:,2))/sum((A(:,1)==k))];end