用索引组matlab计算矩阵的矩阵

时间:2013-09-02 08:28:56

标签: matlab grouping matrix-indexing

我有以下数据:

A = [1 2 ; 3 2; 4 7; 10 2; 6 7; 10 9]
B = [1 2 3; 4 4 9; 1 8 0; 3 7 9; 3 6 8]
C = [4; 10; 6; 3; 1]

A =
    1     2
    3     2
    4     7
   10     2
    6     7
   10     9

B =
    1     2     3
    4     4     9
    1     8     0
    3     7     9
    3     6     8

C.' =
    4    10     6     3     1

对于A(:,2)中的每个唯一值,我需要在A(:,1)中取相应的值, 在C中查找其值,然后获取B中的相关行并计算其均值。 结果应为length(unique(A(:,2)) x size(B,2);

此示例的预期结果:

  • 值“2”:来自B的第2,4和5行的平均值 说明:与A中的值“2”对应的索引1,3和10是              在C的指数2,4,5中。

相应地:

  • 值“7”:来自B的第1行和第3行的平均值。
  • 值“9”:来自B的第2行的平均值。

我现在通过在unique上应用A并迭代每个值,搜索正确的索引来计算它。我的数据集很大,所以需要很长时间。我该如何避免循环?

3 个答案:

答案 0 :(得分:6)

让我们一步一步地做你在问题中说的话:

  1. 对于 A(:, 2)中的每个唯一值:

    [U, ia, iu] = unique(A(:, 2));
    
  2. 获取 A(:, 1) 中的相应值,并在 C中查找其值:

    [tf, loc] = ismember(A(:, 1), C);
    

    为了以防万一,我们还建议确保在C中实际找到所有值:

    assert(all(tf))
    
  3. 然后获取 B 中的相关行并计算其均值

    [X, Y] = meshgrid(1:size(B, 2), iu);
    result = accumarray([Y(:), X(:)], reshape(B(loc, :), 1, []), [], @mean);
    
  4. 希望这有帮助! :)

    实施例

    %// Sample input
    A = [1 2 ; 3 2; 4 7; 10 2; 6 7; 10 9];
    B = [1 2 3; 4 4 9; 1 8 0; 3 7 9; 3 6 8];
    C = [4; 10; 6; 3; 1];
    
    %// Compute means
    [U, ia, iu] = unique(A(:, 2));
    [tf, loc] = ismember(A(:, 1), C);
    [X, Y] = meshgrid(1:size(B, 2), iu);
    result = accumarray([Y(:), X(:)], reshape(B(loc, :), [], 1), [], @mean);
    

    结果是:

    result = 
       3.3333   5.6667   8.6667
       1.0000   5.0000   1.5000
       4.0000   4.0000   9.0000
    

答案 1 :(得分:3)

这是另一种没有arrayfunaccumarray使用良好的旧式矩阵乘法的解决方案:

r = bsxfun(@eq, A(:,1), C')*(1:numel(C))'; 
[~,m,n] = unique(A(:,2));
f=histc(n, 1:numel(m));
result = diag(1./f)*bsxfun(@eq, 1:numel(m), n).'*B(r,:);

我对其他两个解决方案进行了基准测试,看起来比两者都要快。重复1000次:

  • 此方法需要0.205650秒。
  • Eitan T的解决方案需要0.546976秒。
  • matlabit的解决方案需要1.619039秒。

以下是基准代码:

N = 1e3;

tic
for k=1:N,
    r = bsxfun(@eq, A(:,1), C')*(1:numel(C))'; % faster than [~,r] = ismember(A(:,1), C)
    [~,m,n] = unique(A(:,2));
    f=histc(n, 1:numel(m));
    result2 = diag(1./f)*bsxfun(@eq, 1:numel(m), n).'*B(r,:);
end
toc

tic
for k=1:N,
    [U, ia, iu] = unique(A(:, 2));
    [tf, loc] = ismember(A(:, 1), C);
    [X, Y] = meshgrid(1:size(B, 2), iu);
    result1 = accumarray([Y(:), X(:)], reshape(B(loc, :), [], 1), [], @mean);
end
toc

tic
for k=1:N,
    D = [arrayfun(@(x) find(C == x,1,'first'), A(:,1) ), A(:,2)];
    data = [B(D(:,1),:), D(:,2)];
    st = grpstats(data(:,1:3),data(:,4:4),{'mean'});
end
toc

答案 2 :(得分:1)

谢谢, 我还想到了:

D = [arrayfun(@(x) find(C == x,1,'first'), A(:,1) ), A(:,2)];
data = [B(D(:,1),:), D(:,2)];
st = grpstats(data(:,1:3),data(:,4:4),{'mean'});