How to calculate the weighted average over a cell-array of arrays?
In generalisation of my previous question, how can a weighted average over cell elements (that are and shall remain arrays themselves) be performed?
开发者_开发百科
I'd start by modifying gnovice's answer like this:
dim = ndims(c{1}); %# Get the number of dimensions for your arrays
M = cat(dim+1,c{:}); %# Convert to a (dim+1)-dimensional matrix
meanArray = sum(M.*weigth,dim+1)./sum(weigth,dim+1); %# Get the weighted mean across arrays
And before that make sure weight
has the correct shape. The three cases that I think need to be taken care of are
- weight = 1 (or any constant) => return the usual mean value
- numel(weight) == length(c) => weight is per cell-element c{n} (but equal for each array element for fixed n)
- numel(weight) == numel(cell2mat(c)) => each array-element has its own weight...
Case one is easy, and case 3 unlikely to happen so at the moment I'm interested in case 2: How can I transform weight into a array such that M.*weight
has the correct dimensions in the sum above? Of course an answer that shows another way to obtain a weighted averaged is appreciated as well.
edit In fact, case 3 is even more trivial(what a tautology, apologies) than case 1 if weight has the same structure as c.
Here's an example of what I mean for case 2:
c = { [1 2 3; 1 2 3], [4 8 3; 4 2 6] };
weight = [ 2, 1 ];
should return
meanArray = [ 2 4 3; 2 2 4 ]
(e.g. for the first element (2*1 + 1*4)/(2+1) = 2)
After familiarizing myself with REPMAT, now here's my solution:
function meanArray = cellMean(c, weight)
% meanArray = cellMean(c, [weight=1])
% mean over the elements of a cell c, keeping matrix structures of cell
% elements etc. Use weight if given.
% based on http://stackoverflow.com/q/5197692/321973, courtesy of gnovice
% (http://stackoverflow.com/users/52738/gnovice)
% extended to weighted averaging by Tobias Kienzler
% (see also http://stackoverflow.com/q/5231406/321973)
dim = ndims(c{1}); %# Get the number of dimensions for your arrays
if ~exist('weight', 'var') || isempty(weight); weight = 1; end;
eins = ones(size(c{1})); % that is german for "one", creative, I know...
if ~iscell(weight)
% ignore length if all elements are equal, this is case 1
if isequal(weight./max(weight(:)), ones(size(weight)))
weight = repmat(eins, [size(eins)>0 length(c)]);
elseif isequal(numel(weight), length(c)) % case 2: per cell-array weigth
weight = repmat(shiftdim(weight, -3), [size(eins) 1]);
else
error(['Weird weight dimensions: ' num2str(size(weight))]);
end
else % case 3, insert some dimension check here if you want
weight = cat(dim+1,weight{:});
end;
M = cat(dim+1,c{:}); %# Convert to a (dim+1)-dimensional matrix
sumc = sum(M.*weight,dim+1);
sumw = sum(weight,dim+1);
meanArray = sumc./sumw; %# Get the weighted mean across arrays
精彩评论