【问题标题】:Vectorized range checking in MatlabMatlab中的矢量化范围检查
【发布时间】:2014-09-26 08:28:15
【问题描述】:

在尝试将算法从 C# 移植到 Matlab 时,我发现 Matlab 在运行 for 循环时效率低下。因此,我想对算法进行矢量化。

我有以下输入:

低档:

[ 00 10 20 30 40 50 ... ]

远距离:

[ 10 20 30 40 50 60 ... ]

这些数组长度相等。

我现在有第三个数组Values(可以是任何长度),对于这个数组,我想计算Values 元素在lowerange(i)highrange(i) 之间的出现次数(你可以看到我来了来自 for 循环)。

输出应该是一个长度为低范围/高范围的数组。

所以用上面的数组输入LineData:

[ 1 2 3 4 6 11 12 16 31 34 45 ]

我希望得到:

[ 05 03 00 02 01 00 ...  ]

我尝试了(对我而言)显而易见的事情:

LineData(LineData < PixelEnd & LineData > PixelStart) 

但这不起作用,因为它只是逐个元素地检查元素上的 LineData。它不会尝试对LineData 中的所有值进行比较。

不幸的是,由于我还不习惯以 Matlab 的“向量”方式思考,所以我无法想出其他任何东西,更不用说从记忆中知道所有适用的指令了。

【问题讨论】:

  • 如果Values 中的任何元素像1020 这样落在边界上怎么办?另外,lowrangehighrange的元素之间的间隔是否相同,即给定数据中的10
  • @Divakar 好点...我的数据是由物理过程生成的,因此可能会发生某些事情正好落在边界上。但是,我认为其中一个答案中建议的命中会为此类事件提供规定(但实际上,我需要检查它们是什么)。另一方面,是的,间隔将始终保持不变。

标签: arrays algorithm matlab vector vectorization


【解决方案1】:

当您正在寻找具有给定边缘的基本直方图时,您可以使用 Matlabs 内置函数 histc:

values = [ 1 2 3 4 6 11 12 16 31 34 45 ];
edges = 0:10:60;
histc(values, edges)

ans =

 5     3     0     2     1     0     0

【讨论】:

  • 我认为它会足够快!看histc 的明智之举适合这里。 +1
【解决方案2】:

对于具有相同间隔并从 0 开始的范围,这是基于 bsxfun 的计数方法 -

LineData = [ 1 2 3 4 6 11 12 16 31 34 45 ] %// Input

interval = 10; %// interval width
num_itervals = 6; %// number of intervals

%// Get matches for each interval and sum them within each interval for the counts
out = sum(bsxfun(@eq,ceil(LineData(:)/interval),1:num_itervals)) 

输出 -

LineData =
     1     2     3     4     6    11    12    16    31    34    45
out =
     5     3     0     2     1     0

假设最后一个区间是输入数据最大值的区间,您也可以尝试基于 diff + indexing 的方法 -

LineData = [ 1 2 3 4 6 11 12 16 31 34 45 ] %// Input
interval = 10; %// interval width

labels = ceil(LineData(:)/interval); %// set labels to each input entry
df_labels = diff(labels)~=0; %// mark the change of labels
df_labels_pos = find([df_labels; 1]); %// get the positions of label change
intv_pos= labels([true;df_labels]);%// position of each interval with nonzero counts

%// get counts from interval between label position change and put at right places
out(intv_pos) =  [ df_labels_pos(1) ; diff(df_labels_pos)]; 

【讨论】:

  • 我想知道在运行大量迭代时这是否会比 histc 更快/更慢...
  • @Kris LineData 有多大?它的范围是多少(最小和最大)?你会在循环中运行这个计数问题吗? histc 被称为是相当快的,如果你只是要数数,但你可以测试一下,对吧?
  • 我的经验是histc 既快速又可读。如果您比较速度,请包括accumarray-version(我不希望在 1d 直方图情况下获胜):bins = floor(interp1(0:10:60, 1:7, LineData)); 后跟 out = accumarray(bins', ones(length(LineData),1));
  • @Nras 进行了几次测试,bsxfun 肯定落后了,但基于diff + indexing 的方法与基于histc 的方法相差不远。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多