我需要生成下面解释的矩阵。如何有效地从矩阵中的每个重复行获取最小值和最大值?
假设我将以下数据作为矩阵:
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
如何有效地生成此矩阵?
答案 0 :(得分:5)
这是使用accumarray
与unique
结合使用的经典案例。这种方法带来的额外好处是,您不仅限于R2015b或更高版本,即使答案是解决问题的同样好方法。
使用unique
同时查找x
和y
列的所有唯一行。您将希望第一个输出找到这些唯一行,第三个输出为每行分配一个唯一的整数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
的组,最小和最大值为-60
和60
,因此这些元素之间的绝对差值为{{1 }}。可以对其余的唯一行执行类似的过程。
答案 1 :(得分:3)
如果您使用的是R2015b或更高版本,请使用findgroups
和splitapply
:
[G, IDx, IDy] = findgroups(A(:, 1), A(:, 2));
Range = splitapply(@(z) abs(min(z) - max(z)), A(:, 3), G);
NewMatrix = [IDx, IDy, Range];
findgroups
就是这样,它会找到所有具有唯一输入组合的组。它返回一个带有组号的向量,并可选择返回每个组的唯一值(IDx
和IDy
,以上)。
splitapply
然后将任何函数应用于每个组中的值。因此,该函数将应用于"组1",然后"组2"等等,类似于cellfun
如何将相同的函数应用于a中的每个元素细胞阵列。