Matlab:避免for循环以在具有相同标签的值中找到最大值 [英] Matlab: avoid for loops to find the maximum among values with same labels

查看:33
本文介绍了Matlab:避免for循环以在具有相同标签的值中找到最大值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要在 matlab 中找到具有相同标签的值中的最大值,并且我试图避免使用 for 循环.

I need to find the maximum among values with same labels, in matlab, and I am trying to avoid using for loops.

具体来说,我有一个标签数组 L 和一个值数组 V,大小相同.我需要生成一个数组S,其中对于L 的每个值都包含V 的最大值.一个例子会更好地解释:

Specifically, I have an array L of labels and an array V of values, same size. I need to produce an array S which contains, for each value of L, the maximum value of V. An example will explain better:

L = [1,1,1,2,2,2,3,3,3,4,4,4,1,2,3,4]

V = [5,4,3,2,1,2,3,4,5,6,7,8,9,8,7,6]

那么,输出数组 S 的值将是:

Then, the values of the output array S will be:

s(1) = 9 (the values V(i) such that L(i) == 1 are: 5,4,3,9 -> max = 9)

s(2) = 8 (the values V(i) such that L(i) == 2 are: 2,1,2,8 -> max = 8)

s(3) = 7 (the values V(i) such that L(i) == 3 are: 3,4,5,7 -> max = 7)

s(4) = 8 (the values V(i) such that L(i) == 4 are: 6,7,8,6 -> max = 8)

这可以通过使用 for 循环遍历数组 LV 来轻松实现,但是在 Matlab 中 for 循环很慢,所以我一直在寻找更快的解决方案.有什么想法吗?

this can be trivially implemented by traversing the arrays L and V with a for loop, but in Matlab for loops are slow, so I was looking for a faster solution. Any idea?

推荐答案

这是 accumarray.

需要考虑三种情况,越来越普遍:

Three cases need to be considered, with increasing generality:

  • 整数标签.
  • 整数标签,指定填充值.
  • 消除差距;或非整数标签.一般情况.

你可以使用

S = accumarray(L(:), V(:), [], @max).';

在你的例子中,这给出了

In your example, this gives

>> L = [1 1 1 2 2 2 3 3 3 4 4 4 1 2 3 7];
>> V = [5 4 3 2 1 2 3 4 5 6 7 8 9 8 7 6];
>> S = accumarray(L(:), V(:), [], @max).'
S =
     9     8     7     8

整数标签,指定填充值

如果在 L 中存在整数之间的间隔,上面将给出不存在标签的 0 结果.如果您想更改该 填充值(例如更改为 NaN),请在 acccumarray 中使用第五个输入参数:

Integer labels, specify fill value

If there are gaps between integers in L, the above will give a 0 result for the non-existing labels. If you want to change that fill value (for example to NaN), use a fifth input argument in acccumarray:

S = accumarray(L(:), V(:), [], @max, NaN).';

例子:

>> L = [1 1 1 2 2 2 3 3 3 4 4 4 1 2 3 7]; %// last element changed
>> V = [5 4 3 2 1 2 3 4 5 6 7 8 9 8 7 6]; %// same as in your example
>> S = accumarray(L(:), V(:), [], @max, NaN).'
S =
     9     8     7     8   NaN   NaN     6

消除间隙;或非整数标签.一般情况

当整数标签之间的间隙很大时,使用填充值可能效率低下.在这种情况下,您可能只想获取 S 中有意义的值,而不需要填充值,即跳过不存在的标签.此外,L 不一定包含整数.

Remove gaps; or non-integer labels. General case

When the gaps between integer labels are large, using a fill value may be inefficient. In that case you may want to get only the meaningful values in S, without fill values, i.e.skip non-existing labels. Also, it may be the case that L doesn't necessarily contain integers.

这两个问题通过应用 unique 使用 accumarray 之前的标签:

These two issues are solved by applying unique to the labels before using accumarray:

[~, ~, Li] = unique(L); %// transform L into consecutive integers
S = accumarray(Li(:), V(:), [], @max, NaN).';

例子:

>> L = [1.5 1.5 1.5 2 2 2 3 3 3 4 4 4 1 2 3 7.8]; %// note: non-integer values
>> V = [5   4   3   2 1 2 3 4 5 6 7 8 9 8 7 6  ]; %// same as in your example
>> [~, ~, Li] = unique(L); %// transform L into consecutive integers
>> S = accumarray(Li(:), V(:), [], @max, NaN).'
S =
     9     5     8     7     8     6

这篇关于Matlab:避免for循环以在具有相同标签的值中找到最大值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆