matlab:将矢量划分为固定大小的重叠块

时间:2013-12-16 11:22:10

标签: matlab vector split range indices

我有一个向量,我希望在cs的移位中拆分为大小为sh的重叠子向量。想象一下输入向量是:

v=[1 2 3 4 5 6 7 8 9 10 11 12 13]; % A=[1:13]

如果chunksize为4(cs=4)且移位为2(sh=2),结果应如下所示:

[1 2 3 4]
[3 4 5 6]
[5 6 7 8]
[7 8 9 10]
[9 10 11 12]

请注意,输入向量不一定能被chunksize整除,因此会丢弃一些子向量。是否有任何快速计算方法,无需使用例如一个for循环? 在一个相关的post中,我发现了如何做到这一点,但在考虑非重叠的子向量时。

5 个答案:

答案 0 :(得分:5)

您可以按以下方式使用功能bsxfun

v=[1 2 3 4 5 6 7 8 9 10 11 12 13]; % A=[1:13]
cs=4;
sh=2;

A = v(bsxfun(@plus,(1:cs),(0:sh:length(v)-cs)'));

以下是它的工作原理。 bsxfun在2个数组上应用一些基本函数并执行一些repmat - 就像输入的大小不适合一样。在这种情况下,我生成第一个块的索引,并添加每个块的偏移量。由于一个输入是行向量而另一个是列向量,因此结果是矩阵。最后,当使用矩阵索引向量时,结果是一个矩阵,这正是您所期望的。

这是一个单行,(几乎)总是很有趣:)。

答案 1 :(得分:2)

我认为最简单的方法实际上是循环。 矢量化解决方案可以更快,但如果结果被正确分配,循环也应该能够正常运行。

v = 1:13
cs = 4;
sh = 2;

myMat = NaN(floor((numel(v) - cs) / sh) + 1,cs);
count = 0;

for t = cs:sh:numel(v)
   count = count+1;
   myMat(count,:) = v(t-cs+1:t);
end

答案 2 :(得分:2)

你有信号处理工具箱吗?然后命令是buffer。首先看一下裸输出:

buffer(v, 4, 2)

ans =
     0     1     3     5     7     9    11
     0     2     4     6     8    10    12
     1     3     5     7     9    11    13
     2     4     6     8    10    12     0

这显然是正确的想法,只需要一点调整就可以为您提供所需的输出:

[y z] = buffer(v, 4, 2, 'nodelay');
y.'

ans =
     1     2     3     4
     3     4     5     6
     5     6     7     8
     7     8     9    10
     9    10    11    12

那就是说,考虑将列向下的向量,因为它更好地匹配大多数用例。例如,每个窗口的平均值只是矩阵的mean,因为列式是默认值。

答案 3 :(得分:1)

您可以使用ndgrid完成此操作:

>> v=1:13; cs=4; sh=2;
>> [Y,X]=ndgrid(1:(cs-sh):(numel(v)-cs+1),0:cs-1)
>> chunks = X+Y
chunks =
     1     2     3     4
     3     4     5     6
     5     6     7     8
     7     8     9    10
     9    10    11    12

关于second syntax of the colon operatorj:i:k)的好处是你不必完全计算k(例如1:2:6[1 3 5])您计划丢弃额外的条目,如此问题。它会自动转到j+m*i,其中m = fix((k-j)/i);

不同的测试:

>> v=1:14; cs=5; sh=2; % or v=1:15 or v=1:16
>> [Y,X]=ndgrid(1:(cs-sh):(numel(v)-cs+1),0:cs-1); chunks = X+Y
chunks =
     1     2     3     4     5
     4     5     6     7     8
     7     8     9    10    11
    10    11    12    13    14

将在v=1:17处形成一个新行。这会根据需要处理所有情况吗?

答案 4 :(得分:0)

这个怎么样?首先,我基于cssh生成起始索引,用于将单个向量切割出全长向量,然后删除idx+cs超过向量长度的所有索引然后我通过arrayfun切出单个子矢量,然后将它们转换成矩阵:

v=[1 2 3 4 5 6 7 8 9 10 11 12 13]; % A=[1:13]
cs=4;
sh=2;

idx = 1:(cs-sh):length(v);
idx = idx(idx+cs-1 <= length(v))
A = arrayfun(@(i) v(i:(i+cs-1)), idx, 'UniformOutput', false);
cell2mat(A')

E.g。对于cs=5; sh=3;,这将给出:

idx =

     1     3     5     7


ans =

     1     2     3     4     5
     3     4     5     6     7
     5     6     7     8     9
     7     8     9    10    11

根据值cs; sh的来源,您可能希望引入一个简单的错误检查,以便cs > 0;以及sh < cs。理论上如果你想在两者之间留下一些价值,那么sh < 0是可能的。

编辑:修正了一个非常小的错误,现在应该针对sh和cs的不同组合运行。