对具有相同 ID 的元素进行分组并找到最大值及其位置

Grouping elements with the same ID and finding the maximum value as well as its location

我有两个长度为16的向量。第一个,r,例如:

r = [1;3;5;7;1;3;6;7;9;11;13;16;9;11;13;16];

r 包含 ID 列表。我想收集 r 中重复 ID 的索引,以便每个组都是一个 ID 的索引列表。然后我会使用这些索引来访问第二个向量 a 并找到每个组的索引上的最大值。

因此,我想使用 ra 生成一个输出向量,这样:

max(a(1),a(5)), max(a(2),a(6)), a(3), a(7), max(a(4),a(8)), max(a(9),a(13)), max(a(10),a(14)), max(a(11),a(15)), max(a(12),a(16))

我也想保留最大值的索引。我怎样才能在 MATLAB 中有效地实现它?

你可以使用unique to assign each unique number in r a unique ID. You can then bin all of the numbers that share the same ID with an accumarray调用的第三个输出,其中key是唯一ID,value是这个唯一ID数组中key对应位置的a的实际值.收集完所有这些值后,使用 accumarray,这样您就可以将这些值用于 r 中的每个唯一值,以引用最大元素中的 a 和 select:

%// Define r and a
r = [1;3;5;7;1;3;6;7;9;11;13;16;9;11;13;16];
a = [...];

%// Relevant code
[~,~,id] = unique(r, 'stable');
out = accumarray(id(:), a(:), [], @max);

unique 中的 'stable' 标志很重要,因为我们要按出现顺序分配唯一 ID。不这样做会在分配 ID 之前先 排序 r 中的值,这不是我们想要的。

这是一个简单的例子。让我设置您的问题,生成一个存储在 a 中的随机 16 元素数组,您试图最终对其进行索引。我们还将设置 r:

rng(123);
a = rand(16,1);
r = [1;3;5;7;1;3;6;7;9;11;13;16;9;11;13;16];

这是 a 的样子:

>> a

a =

    0.6965
    0.2861
    0.2269
    0.5513
    0.7195
    0.4231
    0.9808
    0.6848
    0.4809
    0.3921
    0.3432
    0.7290
    0.4386
    0.0597
    0.3980
    0.7380

通过代码运行后,我们得到:

out =

    0.7195
    0.4231
    0.2269
    0.6848
    0.9808
    0.4809
    0.3921
    0.3980
    0.7380

您可以自己验证这给出了正确的结果。具体来说,第一个元素是a(1)a(5)中的最大值分别为0.6965和0.7195,最大值为0.7195。同样,第二个元素是最大值a(2)a(6),分别是0.2861和0.4231,最大值是0.4231等等


如果您还想记住用于 select 最大元素的索引,这会稍微复杂一些。您需要做的是再次调用 accumarray,但值不会是 a 的值,而是实际的索引值。您将使用 max 的第二个输出来获取所选值的实际位置。然而,由于 max 的性质,我们不能只获取 max 的第二个元素而不显式调用 max 的双输出版本(我真的希望有另一种方法这个... Python 在 NumPy 中有一个函数叫做 numpy.argmax) 并且它不能被正确地封装在一个匿名函数中(即 @(x) ...),所以你需要创建一个自定义函数来执行此操作。

创建一个名为 maxmod 的新函数并将其保存到名为 maxmod.m 的文件中。你会把它放在函数中:

function p = maxmod(vals, ind)
    [~,ii] = max(vals(ind));
    p = ind(ii);

这需要一个数组和一系列索引来访问数组,称为 vals。然后我们找到这些 selected 结果中的最大值,然后 return 哪个索引给了我们最大值。

之后,您可以这样调用 accumarray

%// Define r and a
r = [1;3;5;7;1;3;6;7;9;11;13;16;9;11;13;16];
a = [...];

%// Relevant code
[~,~,id] = unique(r, 'stable');
out = accumarray(id(:), (1:numel(r)).', [], @(x) maxmod(a,x));

这是我现在得到的:

>> out

out =

     5
     6
     3
     8
     7
     9
    10
    15
    16

如果您查看每个值,这反映了我们选择的 a 的哪个位置对应于每个组的最大值。