6

所以我目前正在使用“accumarray”来查找与匹配 ID 相对应的一系列数字的平均值。防爆输入:

ID----Value
1     215
1     336
1     123
2     111
2     246
2     851

我当前的代码使用 ID 作为“分隔符”找到上述值的未加权平均值,这样我就不会将所有值的平均值作为一个数字,而是仅将具有相应 ID 的值的结果分开. 前输出:

ID----Value
1     224.66
2     402.66

为此,我正在使用以下代码:

[ID, ~, Groups] = unique(StarData2(:,1),'stable');
app = accumarray(Groups, StarData2(:,2), [], @mean);

StarData2 是函数的输入。到目前为止,这对我的目的来说非常有效,我需要知道是否可以让 accumarray 给我一个加权平均值,以便可以为应用程序中的每个点(在找到平均值之前)分配一个权重,或者 @mean 可以替换为可以实现此目的的功能。新输入将如下所示:

ID----Value----Weight
1     215     12
1     336     17
1     123     11
2     111     6
2     246     20
2     851     18

新代码必须执行 sum(val(i)*weight(i))/sum(weight) 而不仅仅是标准平均值。感谢您的任何帮助。

4

4 回答 4

7

您可以将行索引用作“vals”(第二个输入)并定义您自己的函数,该函数对accumarray数据组进行加权平均:

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)

示范

data(带有权重的新输入)和您的unique命令开始:

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');

accumarray用法如下(每次更改都要重新定义WeightedMeanFcn 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

手动检查,第一组:

ig = 1;
sum(data(Groups==ig,2).*data(Groups==ig,3))/sum(data(Groups==ig,3))
ans =
  241.1250
于 2014-04-01T19:05:03.383 回答
1

您可以直接计算加权平均值或许多其他函数,而不是使用accumarray,非常容易:

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

您是否有特定的原因希望这样做accumarray

于 2014-04-01T18:29:39.467 回答
1

@Naveh - 通常,建议避免在 Matlab 中使用循环。具体来说,如果您拥有包含许多组的大量数据 - 它可能会非常慢。

使用accumarray是要走的路,但定义索引的函数,正如@chappjc 所建议的那样,容易出错,因为为了被匿名函数捕获,你必须确保

data 不是 WeightedMeanFcn 的输入。必须在定义WeightedMeanFcn之前定义,

正如@chappjc 在他的评论中所说。

克服这个问题的轻微修改是使用accumarray两次:

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

有时您可能需要将[]参数替换为所需输出的大小。

于 2017-09-10T21:31:18.063 回答
-1

您要计算的不是加权平均值,而是加权直方图。
可以在此处找到加权直方图的 mex 实现。不过,accumarray这是安全的方式。

于 2014-04-03T16:11:53.403 回答