【问题标题】:Accessing Ranges of Data in Vectorized Way MATLAB以向量化方式 MATLAB 访问数据范围
【发布时间】:2013-07-30 06:03:34
【问题描述】:

我在变量vdata 中有一个数据列向量和一个索引列表idx。我想在x 之前的索引处访问vdata,在idx 中的每个索引之后访问x。我会在 for 循环中执行此操作的一种方法是:

x = 10;
accessed_data = [];
for (ii = 1:length(idx))
    accessed_data = vdata(idx-x:idx+x);
end

有没有办法在矢量化函数中做到这一点?我在这里找到了一个非常相似的问题的解决方案:Addressing multiple ranges via indices in a vector 但我不明白代码:(。

【问题讨论】:

  • 你到底想要什么结果?每个ii一个行的矩阵?

标签: matlab vectorization


【解决方案1】:

假设min(idx)-x>0max(idx)+x<=numel(vdata) 那么你可以简单地做

 iidx = bsxfun(@plus, idx(:), -x:x); % create all indices
 accessed_data = vdata( iidx );

【讨论】:

  • 他们是什么时候开始允许您将bsxfun 应用于两个转置向量的?我总是记得必须先构建一个矩阵,以便两个输入数组的非单维维度相互匹配?但现在我看到这在 R2012b 中有效。我糊涂了吗?
  • @horchler AFAIK 一直都是这样。有关更多示例,请参阅bsxfun 标签 wiki(欢迎贡献)。
  • R2007a 中的doc for bsxfun(该功能的首次亮相)似乎支持您。我不知道我是否接受了这个想法。
  • BSXFUN 是正确的。我以前从未听说过这个功能,但这正是我所需要的。谢谢 Shai 和 horchler!
  • @navr91 bsxfun 是一个很棒的功能。访问其bsxfun wiki
【解决方案2】:

一种使用直接索引而不是for 循环的方案:

xx = (-x:x).';                            % Range of indices
idxx = bsxfun(@plus,xx(:,ones(1,numel(idx))),idx(:).'); % Build array
idxx = idxx(:);                           % Columnize to interleave columns
idxx = idxx(idxx>=1&idxx<=length(vdata)); % Make sure the idx+/-x is valid index
accessed_data = vdata(idxx);              % Indices of data

第二行可以替换为@Shai 答案中第一行的形式。该方案检查所有结果索引是否有效。因为可能必须删除一些,所以您最终可能会得到一个参差不齐的数组。解决这个问题的一种方法是使用元胞数组,但这里我只是将idxx 设为向量,因此accessed_data 也是如此。

【讨论】:

    【解决方案3】:

    这会在矩阵中给出解决方案,idx 中的每个值对应一行。它假定idx 中的所有值都大于或等于x,并且小于或等于length(vdata)-x

    % Data
    x = 10;
    idx = [12 20 15];
    vdata = 1:100;
    
    ind = repmat(-x:x,length(idx),1) + repmat(idx(:),1,2*x+1);
    vdata(ind)
    

    【讨论】:

    • 纯属无知,恐怕。 bsxfun 更快吗?
    • 查看bsxfun标签维基了解更多信息
    • @Shai:在过去,repmat 没有作为本机函数实现,它确实可能很慢。现在少了(我不确定这发生在哪个版本中)。此外,在我自己的硬件上,我发现bsxfun 实际上比复制足够小的数组的方法要慢。不知道为什么(内存分配速度与 CPU 速度?)。但是,如果要针对最坏的情况进行优化,那么bsxfun 是不二之选。
    猜你喜欢
    • 2016-12-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-24
    相关资源
    最近更新 更多