在Matlab中没有循环的向量重叠的多个选择

时间:2016-03-16 12:46:05

标签: matlab vectorization

假设我在matlab中有一个长度为v的向量m。我想从中提取一些切片,将它们放入一个新的矩阵中。我会有一个hopsize h_size,一个窗口长度win_len和一些跳转num_j。如何在不使用循环的情况下完成此操作?循环版本将是:

for i = 1:num_j
   slice(i,:) = v(1+(i-1)*h_size : win_len+(i-1)*h_size);
end

代码应该与算法的这个变体一起使用,其中我对切片和hopsizes的所有组合都有一个双for循环。在这种情况下,我有不同长度的切片,所以我将使用一个单元格数组:

sliceInd = 0;
for i = 1:num_j
   for j = i:num_j
      sliceInd = sliceInd + 1;
      slice{sliceInd} = v(1+(i-1)*h_size : win_len+(j-1)*h_size);
   end
end

1 个答案:

答案 0 :(得分:1)

对于您的第一种情况,您可以使用bsxfun为您创建索引。

slice = v(bsxfun(@plus, 1:h_size:h_size*num_j, (0:win_len-1).').');

<强>解释

这基本上是它确定了你的所有起始位置:

starts = 1:h_size:(h_size * num_j);

然后从这些位置开始,我们想要采样win_len点。要对给定的起始位置执行此操作,我们可以使用此公式。

inds = starts(k) + 0:(win_len - 1);

然后,我们可以使用bsxfun所有起始位置执行此操作。

bsxfun(@plus, 1:h_size:h_size*num_j, (0:win_len-1).').';

然后我们将其用作v的索引以获得最终结果。

这假设您已正确选择变量,这样您就不会尝试在v的末尾进行索引(即(h_size * num_j) + win_len - 1 > numel(v)时。

修改

如果您确实需要循环浏览各种h_sizewin_len值的选项,则可以使用嵌套的arrayfun调用来获取结果而不进行循环,但这实际上有点凌乱

R = arrayfun(@(h,w)arrayfun(@(x)v(x+(0:w-1)), 1:h:h*num_j, 'uni', 0), hrange, wrange, 'uni', 0);
slice = cat(2, R{:});

您可以在h_size中定义hrange值的范围,在win_len中定义wrange值。

<强> EDIT2

如果您尝试在vh_size的多个排列中同时对多行w_len执行此操作。我可能会以这种方式循环它。

% Anonymous function to get the indices
getinds = @(h,w)bsxfun(@plus, 1:h:h*num_j, (0:w-1).').';

% All permutations of h_size and w_len
[hh, ww] = meshgrid(hrange, wrange);

alldata = cell(size(hh));

for k = 1:numel(hh)
    inds = getinds(hh(k), ww(k));
    V = reshape(v(:, inds), [size(v, 1), size(inds)]);

    % V is a 3D array where the info for each window is along the third dim
    % i.e. Hop #1 for the first for of v is V(1,1,:)

    % Do whatever you want here

    % ... or store data in cell array for processing later
    alldata{k} = V;
end