【问题标题】:vectorising multiple calls of Matlab 'find'向量化 Matlab 'find' 的多个调用
【发布时间】:2024-01-18 19:52:01
【问题描述】:

我对 Matlab 的“查找”功能进行了大量调用。例如,下面应该给出本质:

x=rand(1,10^8);
indx=zeros(1,10^8);
for i=1:10^8
    indx(i) = find([0.2, 0.52, 0.76,1] < x(i), 1, 'last');
end

有没有办法对这段代码进行矢量化以加快速度?仅将 x 作为向量包含在内会产生错误。如果矢量化是不可能的,那么任何其他关于速度的建议将不胜感激。我希望解决的实际问题有一个相当长的向量来代替 [0.2, 0.52, 0.76,1],因此任何解决方案都不应依赖于我提供的特定向量。

谢谢。

【问题讨论】:

  • 在该示例中,结果始终为4。你确定要'last'吗?
  • 对....我已经翻转了不等式(在我最近的编辑中),使它变得不平凡。只是试图构建一个以简单方式捕捉真正问题的玩具问题。感谢您发现它。
  • 警告:如果不等式不满足x,您的循环将出错。尝试使用x 中小于0.2 的任何值

标签: matlab find vectorization


【解决方案1】:

对于 MATLAB 版本 R2015a 和更新版本crjones 的答案给出了使用 discretize 的最佳选择:

edges = [0.2, 0.52, 0.76, 1];
indx = discretize(x, edges, 'IncludedEdge', 'right');

x 中超出edges 范围的任何值都将使用NaN 作为其索引。


对于 MATLAB 版本 R2014b 和更新版本,您还可以使用 histcounts:

[~, ~, indx] = histcounts(x, edges);

discretize 的不同之处在于,您还可以获取每个 bin(第一个输出)中的值的计数,x 中超出edges 范围的值的索引将是0


对于 R2014b 之前的 MATLAB 版本,您可以使用 histc(在较新版本中已弃用):

[~, indx] = histc(x, edges);

同样,您还可以获取每个 bin(第一个输出)中值的计数,x 中超出edges 范围的值的索引将是0

【讨论】:

    【解决方案2】:

    根据您的示例,您可能需要考虑为此使用 discretize 函数:

    x=rand(1,10^8);
    edges = [0.2, 0.52, 0.76, 1];
    indx = discretize(x, edges, 'IncludedEdge', 'right'); 
    

    请注意,超出范围的情况将导致 NaN。

    % small test case
    % x = [0.5198, 0.0768, 0.6788, 0.9496]
    % indx = discretize(x, edges, 'IncludedEdge', 'right')
    % answer:   1   NaN   2     3
    

    当然,这仅适用于您试图找到 x 适合有序集合的位置。

    【讨论】:

    • 多么有用的功能。它很快......对我来说将计算时间减少了大约 100 倍。谢谢!
    【解决方案3】:

    Compare 你的向量与x 得到一个逻辑矩阵,表明vec 中的值小于x。将该逻辑矩阵与表示列下标的列向量相乘。使用max 找到满足不等式的最大(最后一个)索引。对于不等式不满足的情况,你将得到零。

    vec = [0.2, 0.52, 0.76, 1];    %Your vector
    indx = bsxfun(@lt, vec(:), x); %Making 'vec' a column matrix and comparing with 'x'
    indx = max(bsxfun(@times, indx, (1:numel(vec)).')); %The required result
    

    对于 R2016b 及更高版本,您可以使用隐式扩展代替bsxfun

    indx = vec(:) < x ;  
    indx = max(indx .* (1:numel(vec)).');
    

    【讨论】:

    • 并不是说在大多数情况下它会很明显,但flip(end:-1:1) 快大约 2 倍。
    最近更新 更多