Calculate mean of columns for a unique value of column variable?
7 Ansichten (letzte 30 Tage)
Ältere Kommentare anzeigen
Madan Kumar
am 18 Jun. 2017
Bearbeitet: dpb
am 18 Jun. 2017
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 Kommentare
Akzeptierte Antwort
the cyclist
am 18 Jun. 2017
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
Weitere Antworten (2)
dpb
am 18 Jun. 2017
Bearbeitet: dpb
am 18 Jun. 2017
>> [~,~,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 Kommentare
Andrei Bobrov
am 18 Jun. 2017
Bearbeitet: Andrei Bobrov
am 18 Jun. 2017
[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 Kommentare
the cyclist
am 18 Jun. 2017
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.
Siehe auch
Kategorien
Mehr zu Elementary Math finden Sie in Help Center und File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!