【问题标题】:MATLAB Accumarray weighted meanMATLAB Accumarray 加权平均值
【发布时间】:2014-05-12 14:08:30
【问题描述】:

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

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

我当前的代码找到上述值的未加权平均值,使用 ID 作为“分隔符”,这样我就不会将所有值的平均值作为一个数字,而是将结果单独计算为有对应的ID。 EX 输出:

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) 而不仅仅是标准平均值。感谢您的帮助。

【问题讨论】:

    标签: matlab average mean accumarray


    【解决方案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 执行此操作?

    【讨论】:

      【解决方案2】:

      您可以将行索引用作“vals”(second inputaccumarray)并定义您自己的函数来对数据组进行加权平均:

      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
      

      【讨论】:

      • 注意:data 不是WeightedMeanFcn 的输入。它必须在定义WeightedMeanFcn 之前 定义!那么它将是captured by the anonymous function
      • 这很好,但我得到的输出是错误的,所以我正在更新 OP 以显示输入和输出的确切样式。
      • @ImmortalxR WeightedMeanFcn = @(x) sum(StarData4(x,5).*StarData4(x,6))/sum(StarData4(x,6))。我正在修改我的代码,使权重和值更加明确,而不是列。
      • 太棒了!效果很好。我尝试自己进行类似的更改,但没有奏效,但这很棒!
      • @ImmortalxR 太棒了!只需记下我所说的每次更改数据数组时都必须重新定义匿名函数,因为该函数在定义 data 数组时在内部存储它。
      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

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

        使用accumarray 是可行的方法,但是按照@chappjc 的建议定义索引函数很容易出错,因为为了被匿名函数捕获,您必须确保

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

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

        为了解决这个问题,稍作修改是使用accumarray 两次:

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

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

        【讨论】:

        • 只有一个建议:使用@sum 而不是@mean
        猜你喜欢
        • 1970-01-01
        • 2018-11-08
        • 1970-01-01
        • 1970-01-01
        • 2016-05-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-08-06
        相关资源
        最近更新 更多