【问题标题】:MATLAB find mean of column in matrix using two different indicesMATLAB使用两个不同的索引找到矩阵中列的平均值
【发布时间】:2013-04-13 01:04:20
【问题描述】:

我有一个 22007x3 矩阵,第 3 列中包含数据,第 1 列和第 2 列中有两个单独的索引。

例如。

x = 

    1   3   4
    1   3   5
    1   3   5
    1   16  4
    1   16  3
    1   16  4
    2   4   1
    2   4   3
    2   11  2
    2   11  3
    2   11  2

当第 1 列中的值相同且第 2 列中的值相同时,我需要找到第 3 列中值的平均值,最终得到如下结果:

ans = 

    1   3   4.6667
    1   16  3.6667
    2   4   2
    2   11  2.3333

请记住,在我的数据中,第 1 列和第 2 列中的值出现的次数可能不同。

我已经尝试过的两个选项是 meshgrid/accumarray 选项,使用两个不同的 unique 函数和一个 3D 数组:

[U, ix, iu] = unique(x(:, 1));
[U2,ix2,iu2] = unique(x(:,2));
[c, r, j] = meshgrid((1:size(x(:, 1), 2)), iu, iu2);
totals = accumarray([r(:), c(:), j(:)], x(:), [], @nanmean);

这给了我这个:

??? Maximum variable size allowed by the program is exceeded.

Error in ==> meshgrid at 60
    xx = xx(ones(ny,1),:,ones(nz,1));

和循环选项,

for i=1:size(x,1)
    if x(i,2)== x(i+1,2);
        totals(i,:)=accumarray(x(:,1),x(:,3),[],@nanmean);
    end
end

这显然是非常非常错误的,尤其是因为x(i+1,2) 位。

我还在考虑根据第 1 列中的值出现的次数创建单独的矩阵,但这会很长且效率低下,所以我不愿意走这条路。

【问题讨论】:

    标签: matlab loops mean


    【解决方案1】:

    使用unique(...,'rows') 对前两列进行分组,然后仅累积第三列(始终是仅在真正发生累积的地方累积的最佳方法,从而避免索引,即前两列,您可以使用unX 重新附加):

    [unX,~,subs] = unique(x(:,1:2),'rows');
    out          = [unX accumarray(subs,x(:,3),[],@nanmean)];
    
    out =
                1            3       4.6667
                1           16       3.6667
                2            4            2
                2           11       2.33
    

    【讨论】:

    【解决方案2】:

    这是使用稀疏矩阵数学的理想机会。

    x = [ 1 2 5;
          1 2 7;
          2 4 6;
          3 4 6;
          1 4 8;
          2 4 8;
          1 1 10]; % for example
    
    SM = sparse(x(:,1),x(:,2), x(:,3); 
    disp(SM)
    

    结果:

    (1,1)   10
    (1,2)   12
    (1,4)    8
    (2,4)   14
    (3,6)    7
    

    如您所见,我们一口气完成了“将相同的索引累积到同一个容器中”。现在你需要知道你有多少元素:

    NE = sparse(x(:,1), x(:,2), ones(size(x(:,1))));
    disp(NE);
    

    结果:

    (1,1)   1
    (1,2)   2
    (1,4)   1
    (2,4)   2
    (3,6)   1
    

    最后,您将一个除以另一个以获得平均值(仅使用具有值的元素):

    matrixMean = SM;
    nz = find(NE>0);
    matrixMean(nz) = SM(nz) ./ NE(nz);
    

    如果你然后disp(matrixMean),你会得到

    (1,1)    10
    (1,2)     6
    (1,4)     8
    (2,4)     7
    (3,6)     7
    

    如果你想以不同的方式访问单个元素,那么在你计算了 SM 和 NE 之后,你可以这样做

    [i j n] = find(NE);
    matrixMean = SM(i,j)./NE(i,j);
    disp([i(:) j(:) nonzeros(matrixMean)]);
    

    【讨论】:

      猜你喜欢
      • 2012-09-12
      • 2018-12-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-23
      • 1970-01-01
      • 2011-10-21
      • 1970-01-01
      相关资源
      最近更新 更多