对具有相同 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
并找到每个组的索引上的最大值。
因此,我想使用 r
和 a
生成一个输出向量,这样:
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
的哪个位置对应于每个组的最大值。
我有两个长度为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
并找到每个组的索引上的最大值。
因此,我想使用 r
和 a
生成一个输出向量,这样:
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
的哪个位置对应于每个组的最大值。