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

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

问题描述

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

pre $ 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的值将是:< (1)= 9(V(i)使得L(i)== 1是:5,4 (i)= 2,3(2),3(9)=> 9)

s(2)= 8 (3)= 7(使得L(i)= 3的值V(i)是:3,4,5,7-> max = 7 )

s(4)= 8(使得L(i)== 4的值V(i)是:6,7,8,6 - > max = 8)

这可以通过遍历数组 L V 用for循环,但是在Matlab for循环中很慢,所以我正在寻找一个更快的解决方案。任何想法?

解决方案

这是 accumarray

需要考虑三种情况,通用性越来越高:
$ b


  • 整型标签

  • 整型标签,请指定填充值。

  • 清除间隙;或非整数标签。一般情况下。


整数标签



您可以使用

  S = accumarray(L(:),V(:),[],@max)。 

在你的例子中,这给出了

 >> L = [1 1 1 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 中使用第五个输入参数。 code $:

$ $ $ $ $ $ $ $ $ $ $ $ $ S $ accumarray(L(:),V(:),[],@ NAN)'。

示例:

 >> L = [1 1 1 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,NaN)'
S =
9 8 7 8 NaN NaN 6



清除间隙;或非整数标签。一般情况下



当整数标签之间的差距很大时,使用填充值可能是低效的。在这种情况下,您可能只想在 S 中取得没有填充值的有意义的值,即跳过不存在的标签。此外,可能是 L 不一定包含整数。



这两个问题可以通过应用 unique code> ,然后使用 accumarray

  [〜,〜,Li] =唯一(L); %//将L转换为连续的整数
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]; %//注意:非整数值
>> V = [5 4 3 2 1 2 3 4 5 6 7 8 9 8 7 6]; %//与你的例子相同
>> [〜,〜,Li] =唯一(L); %//将L转换为连续的整数
>> S $ accumarray(Li(:),V(:),[],@ max,NaN)。'
S =
9 5 8 7 8 6


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

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]

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)

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?

解决方案

This is a standard job for accumarray.

Three cases need to be considered, with increasing generality:

  • Integer labels.
  • Integer labels, specify fill value.
  • Remove gaps; or non-integer labels. General case.

Integer labels

You can just use

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

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).';

Example:

>> 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

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.

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).';

Example:

>> 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天全站免登陆