Calculate mean of columns for a unique value of column variable?
7 次查看(过去 30 天)
显示 更早的评论
I have a matrix of 38767*31. I want to calculate mean of columns for unique value of variable in columns (in first row).Let me clarify my problem.
Let
A=[1 2 1 2 1 1 2 1 1
3 2 1 2 3 4 5 6 2
2 1 2 1 3 5 4 2 6]
for unique value for 1st row of A, I have to calculate mean of all corresponding columns. I mean I should get as follows,
B=[1 2; 3.66 3; 3.33 2];
for unique of 1st row (=1), mean of corresponding values (3+1+3+4+6+1)/6=3.166 for 2nd row and (2+2+3+5+2+6)/3=3.33 for 3rd row. for value of 1st row (=2), mean of corresponding values (2+2+5)/3=3 for 2nd row and (1+1+4)/3=2 for 3rd row.Hope I am understood. I tried using accumarray but not able to do. my code is,
A=importdata('abc.dat');
y=accumarray(unique(A(1,:)),A(1,:),[],@mean));
It shows following error, Second input VAL must be a vector with one element for each row in SUBS, or a scalar.? Help. Thanks in advance.
0 个评论
采纳的回答
the cyclist
2017-6-18
This will do what you want with a for loop:
A = [1 2 1 2 1 1 2 1 1
3 2 1 2 3 4 5 6 2
2 1 2 1 3 5 4 2 6];
[uniqueA1,~,k] = unique(A(1,:));
numberUniqueA1 = numel(uniqueA1);
meanArray = zeros(size(A,1),numberUniqueA1);
for nu = 1:numberUniqueA1
indexToThisUniqueValue = (nu==k)';
meanArray(:,nu) = mean(A(:,indexToThisUniqueValue),2);
end
更多回答(2 个)
dpb
2017-6-18
编辑:dpb
2017-6-18
>> [~,~,ib]=unique(A(1,:));
>> C=A(2,:);
>> accumarray(ib,C,[],@mean)
ans =
3.1667
3.0000
>>
Unfortunately, accumarray only works on a vector val input, not columns in an array (it's convoluted-enough already without that complication so that's understandable although would be the cat's meow here, indeed.)
Let's see if there's another way without looping over every column...hmmm....well, let's try
>> ix=A(1,:);
>> u=unique(ix);
>> for i=1:length(u),mean(A(2:end,ix==u(i)),2),end
ans =
3.1667
3.3333
ans =
3
2
>>
You can mull over how to best code it for your situation...
ADDENDUM:
May not be any better speedwise than the loop, but for the record--
>> arrayfun(@(ix) accumarray(ib,A(ix,:).',[],@mean),2:size(A,1),'uniformoutput',0)
ans =
[2x1 double] [2x1 double]
>> ans{:}
ans =
3.1667
3.0000
ans =
3.3333
2.0000
>>
ib is the previous index vector from unique above, of course...
Try to figure out what that does two years down the road when you come back to it! :)
0 个评论
Andrei Bobrov
2017-6-18
编辑:Andrei Bobrov
2017-6-18
[g,ii] = findgroups(A(1,:)');
out = [ii,splitapply(@mean,A(2:3,:)',g)]';
or
[ii,jj] = ndgrid(A(1,:),1:2);
out = [unique(A(1,:)'), accumarray([ii(:),jj(:)],reshape(A(2:3,:)',[],1),[],@mean)]';
2 个评论
the cyclist
2017-6-18
The second solution can be simplified to
[ii,jj] = ndgrid(A(1,:),1:3);
out = [accumarray([ii(:),jj(:)],reshape(A',[],1),[],@mean)]';
Depending on the depth of one's understanding of accumarray, I feel like this solution is both more elegant and more obfuscated than my for-loop solution. Either way, I would be sure to add some comments so that future you remembers what is going on in this code.
In limited testing, the for-loop solution is the fastest of these.
另请参阅
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!