我有一个向量,我希望在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中,我发现了如何做到这一点,但在考虑非重叠的子向量时。
答案 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
operator(j: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)
这个怎么样?首先,我基于cs
和sh
生成起始索引,用于将单个向量切割出全长向量,然后删除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的不同组合运行。