MATLAB Accumarray weighted mean

拈花ヽ惹草 提交于 2019-11-29 04:37:41

You can use the row index as the "vals" (second input to accumarray) and define your own function that does the weighted mean on group of the data:

Weights = data(:,3); Vals = data(:,2); % pick your columns here
WeightedMeanFcn = @(ii) sum(Vals(ii).*Weights(ii))/sum(Weights(ii));
wmeans = accumarray(Groups, 1:numel(Groups), [], WeightedMeanFcn)

Demonstration

Starting with data (the new input with your weights) and your unique command:

data = [1,215,12; 1,336,17; 1,123,11; 2,111,6; 2,246,20; 2,851,18];
[ID, ~, Groups] = unique(data(:,1),'stable');

The accumarray usage is as follows (redefine WeightedMeanFcn every time you change data!):

>> Weights = data(:,3); Vals = data(:,2); % pick your columns here
>> WeightedMeanFcn = @(ii) sum(Vals(ii).*Weights(ii))/sum(Weights(ii));
>> app = accumarray(Groups, 1:numel(Groups), [], WeightedMeanFcn)
app =
  241.1250
  475.0909

Checking manually, with the first group:

ig = 1;
sum(data(Groups==ig,2).*data(Groups==ig,3))/sum(data(Groups==ig,3))
ans =
  241.1250

Instead of using accumarray, you can directly compute a weighted mean, or many other functions, quite easily:

nIDs = length(unique(ID));
WeightedMean = zeros(nIDs, 1);

for ii = 1:nIDs
    iID = (ID == ii);
    WeightedMean(ii) = (Value(iID)' * Weight(iID)) / sum(Weight(iID));
end

Is there a specific reason you wish to do this through accumarray?

@Naveh - Generally, it is advised to avoid using loops in Matlab. Specifically, if you have a large set of data with many groups - it can be very slow.

Using accumarrayis the way to go, but defining a function of the indices, as suggested by @chappjc, is error-prone, since in order to be be captured by the anonymous function, you must make sure that

data is not an input to WeightedMeanFcn. It must be defined before defining WeightedMeanFcn,

as @chappjc says in his comment.

A slight modification to overcome this problem is to use accumarray twice:

Weights = data(:,3); Vals = data(:,2); % pick your columns here    
app = accumarray(Groups, Weights.*vals, [], @mean)./accumarray(Groups, Weights, [], @mean);

Sometimes you may need to replace the [] argument by the size of the required output.

What you are trying to compute is not a weighted mean, but rather a weighted histogram.
There is a mex implementation of weighted histogram that can be found here. Though, accumarray is the safe way to go about.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!