和行向量如果给定列中的两行或多行匹配(MATLAB)

时间:2015-09-03 03:16:40

标签: arrays matlab matrix

我有一个48x202矩阵,其中matix中的第一列是ID,其余列是第一列中行ID的相关向量。

ID列按照升序排序,多行可以具有相同的ID。

我想总结所有相同的ID,这意味着我想要对矩阵中第一列中具有相同ID的行求和。

结果矩阵应为32x202,因为只有32个ID。

有什么想法吗?

3 个答案:

答案 0 :(得分:1)

我完全采用accumarray以及unique来解决这个问题。与上一个答案一样,让A成为您的矩阵。你会得到你的答案:

[vals,~,id] = unique(A(:,1),'stable');
B = accumarray(id, (1:numel(id)).', [], @(x) {sum(A(x,2:end),1)});
out = [vals cell2mat(B)];

第一行代码生成vals,其中列出了A第一列中显示的所有唯一ID,id分配了唯一的整数ID ,没有任何差距从1到A的第一列中有多少个唯一ID。你想要这样做的原因是为了下一行代码。

accumarray的工作原理是您提供一组键和一组与每个键相关联的值。 accumarray对属于同一个键的所有值进行分组,并对所有值执行某些操作。我们的案例中的键是A第一列中给出的ID,值是矩阵A的实际行位置,从1到最多A行。现在,将所有值收集在一起时的默认行为是将属于同一个键的所有值相加在一起,但我们要做一些不同的事情。我们要做的是,对于A第一列中看到的每个唯一ID,会有一堆行位置映射到相同的ID。我们将使用这些行位置并访问矩阵A并将第二列到结尾的所有列相加。这就是accumarray的第四个参数中的匿名函数正在做什么。 accumarray传统上应该输出单个值,表示映射到键的所有值,但我们通过输出单个单元格来解决这个问题,其中每个单元格条目是映射列的行和。

B的每个元素为vals中的每个对应唯一值提供行总和,因此最后一行代码将这些组合在一起 - vals中的唯一值与相应的值行总和。我不得不使用cell2mat,因为这是一个单元格矩阵,我必须将所有这些转换为数字矩阵才能完成任务。

这是一个看到这个实际行动的例子。我会为一小组数据做这件事:

>> rng(123);
>> A = [[1;1;1;2;2;2;2;3;3;4;4;5;6;7] randi(10, 14, 10)];
>> A

A =

     1     7     4     3     4     5     1    10     3     2     3
     1     3     8     7     5     7     9     9     4     9     6
     1     3     2     1     9     9     7     4     6     4     9
     2     6     2     5     3     6     8     1     7     6     4
     2     8     6     5     5     7     1     4     2     6     8
     2     5     6     5    10     6     6     4     2     6     2
     2    10     7     5     6     7     6     8     4     1     7
     3     7     9     4     7     7     2    10     7    10     9
     3     5     8     5     2     9     2     4     9    10    10
     4     4     7     9     9     1     7     8     6     3     1
     4     4     8    10     7     8     4     6     9     3     5
     5     8     4     6     6     3     7     7     4     6     3
     6     5     4     7     4     2     6     2     4    10     5
     7     1     3     2     4     6     4     4     4    10     6

第一列是我们的ID,下一列是数据。运行我刚写的上面的代码,我们得到:

>> out

out =

     1    13    14    11    18    21    17    23    13    15    18
     2    29    21    20    24    26    21    17    15    19    21
     3    12    17     9     9    16     4    14    16    20    19
     4     8    15    19    16     9    11    14    15     6     6
     5     8     4     6     6     3     7     7     4     6     3
     6     5     4     7     4     2     6     2     4    10     5
     7     1     3     2     4     6     4     4     4    10     6

如果您仔细检查每一行,则对与每个列ID匹配的所有列进行求和会匹配。例如,前三行映射到相同的ID,我们应该总结所有这些行,我们得到相应的总和。第二列等于7+3+3=13,第三列等于4+8+2=14等。

答案 1 :(得分:1)

另一种方法是应用unique,然后使用bsxfun构建一个矩阵,该矩阵乘以输入矩阵的非ID部分将得到结果。

将输入矩阵表示为A。然后:

[u, ~, v] = unique(A(:,1));
result =  [ u bsxfun(@eq, u, u(v).') * A(:,2:end) ];

示例:借鉴@rayryeng's answer,让

A = [ 1     7     4     3     4     5     1    10     3     2     3
      1     3     8     7     5     7     9     9     4     9     6
      1     3     2     1     9     9     7     4     6     4     9
      2     6     2     5     3     6     8     1     7     6     4
      2     8     6     5     5     7     1     4     2     6     8
      2     5     6     5    10     6     6     4     2     6     2
      2    10     7     5     6     7     6     8     4     1     7
      3     7     9     4     7     7     2    10     7    10     9
      3     5     8     5     2     9     2     4     9    10    10
      4     4     7     9     9     1     7     8     6     3     1
      4     4     8    10     7     8     4     6     9     3     5
      5     8     4     6     6     3     7     7     4     6     3
      6     5     4     7     4     2     6     2     4    10     5
      7     1     3     2     4     6     4     4     4    10     6 ];

然后结果是

result =
     1    13    14    11    18    21    17    23    13    15    18
     2    29    21    20    24    26    21    17    15    19    21
     3    12    17     9     9    16     4    14    16    20    19
     4     8    15    19    16     9    11    14    15     6     6
     5     8     4     6     6     3     7     7     4     6     3
     6     5     4     7     4     2     6     2     4    10     5
     7     1     3     2     4     6     4     4     4    10     6

和使用bsxfun创建的中间矩阵是

>> bsxfun(@eq, u, u(v).')
ans =
     1     1     1     0     0     0     0     0     0     0     0     0     0     0
     0     0     0     1     1     1     1     0     0     0     0     0     0     0
     0     0     0     0     0     0     0     1     1     0     0     0     0     0
     0     0     0     0     0     0     0     0     0     1     1     0     0     0
     0     0     0     0     0     0     0     0     0     0     0     1     0     0
     0     0     0     0     0     0     0     0     0     0     0     0     1     0
     0     0     0     0     0     0     0     0     0     0     0     0     0     1

通过此矩阵预乘A意味着添加A的前三行以给出结果的第一行;然后添加以下四行A以给出结果的第二行,等等。

答案 2 :(得分:0)

您可以找到包含unique的唯一行ID,然后循环显示所有这些,并将其他列相加:让A成为您的矩阵,然后

rID = unique(A(:, 1));
B = zeros(numel(rID), size(A, 2));
for ii = 1:numel(rID)
  B(ii, 1) = rID(ii);
  B(ii, 2:end) = sum(A(A(:, 1) == rID(ii), 2:end), 1);
end

B包含您的输出。