MATLAB使用两个不同的索引找到矩阵中的列的平均值

时间:2013-04-19 15:19:01

标签: matlab loops mean

我有一个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列中的值出现次数来创建单独的矩阵,但这样做会很长且效率很低,所以我不愿意走这条路。

2 个答案:

答案 0 :(得分:5)

在前两列上使用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

答案 1 :(得分:1)

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

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