如何有效地从矩阵中的每个重复行获取最小值和最大值

时间:2017-10-16 17:41:12

标签: matlab matrix

我需要生成下面解释的矩阵。如何有效地从矩阵中的每个重复行获取最小值和最大值?

假设我将以下数据作为矩阵:

A = 

    x        y      z 

   -250    -60    -60
   -250    -60    -59
   -250    -60    -58
   -250    -60     58
   -250    -60     59
   -250    -60     60
   -250    -59    -60
   -250    -59    -59
   -250    -59    -58
     .      .      .
     .      .      .
     .      .      .
   -250     59     58
   -250     59     59
   -250     59     60
   -250     60     58
   -250     60     59
   -250     60     60

通过重复行,我的意思是x和y的相同值的多行。现在我希望每个重复值的最小值和最大值为z,这样我就可以生成一个跟随矩阵

      x        y        z 


   -250    -60     abs(min(z) - max(z)) % for all x = -250 and y = -60
   -250    -59     abs(min(z) - max(z)) % for all x = -250 and y = -59

如何有效地生成此矩阵?

2 个答案:

答案 0 :(得分:5)

这是使用accumarrayunique结合使用的经典案例。这种方法带来的额外好处是,您不仅限于R2015b或更高版本,即使答案是解决问题的同样好方法。

使用unique同时查找xy列的所有唯一行。您将希望第一个输出找到这些唯一行,第三个输出为每行分配一个唯一的整数ID,该ID为您提供该行所属的组。然后,您可以将accumarray与自定义映射函数一起使用,该函数可以查找属于同一组的值集的最大值和最小值之间的差异。

[Au, ~, ID] = unique(A(:,1:2), 'rows');
out = accumarray(ID, A(:,3), [], @(z) abs(min(z) - max(z)));
out = [Au out];

第一行代码使用A的前两列查找所有唯一行。第一个输出Au为我们提供了一个矩阵,其中只包含A中前两列的唯一行。第三个输出为前两列的每一行分配一个整数ID。这提供了一种映射,使得相同的行被分配给同一组。我们最后使用accumarray我们使用提供分组的ID,我们使用第三列,以便第三列中的所有值都映射到相同的ID,我们将一些值应用于该值集合。在我们的示例中,我们应用abs(min(z) - max(z))的自定义函数,其中z是一个数组,用于对属于同一ID的所有第三列值进行分组。

我们最终连接矩阵的唯一行与accumarray的输出使我们显示您的预期输出。鉴于您的相当有限的示例,我们在MATLAB中得到以下输出:

>> out

out =

  -250   -60   120
  -250   -59     2
  -250    59     2
  -250    60     2

我们可以验证这是否有效,因为对于映射到x = -250, y = -60的组,最小和最大值为-6060,因此这些元素之间的绝对差值为{{1 }}。可以对其余的唯一行执行类似的过程。

答案 1 :(得分:3)

如果您使用的是R2015b或更高版本,请使用findgroupssplitapply

[G, IDx, IDy] = findgroups(A(:, 1), A(:, 2));
Range = splitapply(@(z) abs(min(z) - max(z)), A(:, 3), G);

NewMatrix = [IDx, IDy, Range];

findgroups就是这样,它会找到所有具有唯一输入组合的组。它返回一个带有组号的向量,并可选择返回每个组的唯一值(IDxIDy,以上)。

splitapply然后将任何函数应用于每个组中的值。因此,该函数将应用于"组1",然后"组2"等等,类似于cellfun如何将相同的函数应用于a中的每个元素细胞阵列。