2013-12-16 74 views
8

我有一個矢量,我想將其分割成大小爲cs的重疊子矢量,換算爲sh。想象中的輸入向量爲:matlab:將矢量劃分爲固定大小的重疊塊

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

給出的2(sh=2)4(cs=4)和換檔的chunksize,結果應該是這樣的:

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

注意,輸入矢量不一定被chunksize整除,因此一些子向量被丟棄。有沒有什麼快速的方法來計算,而不需要使用例如一個for循環? 在相關的post我發現如何做到這一點,但在考慮非重疊子向量時。

回答

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') 

例如爲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 < cssh < 0理論上是可能的,如果你想留下一些值之間。

編輯:修正了一個很小的錯誤,現在應該運行sh和cs的不同組合。

+0

我爲什麼要?它也適用於不同的數字。 'idx'只應該給我的子向量的起始索引,因此,我def。需要cs-sh作爲步驟 - 編輯:我嘗試使用不同的向量和不同數量的'cs'和'sh',它的工作原理非常好。 – tim

+0

對於'cs = 5;我假設起始索引是「1 4 7」而不是「1 3 5 7」。如果是這種情況,可以使用'idx = 1:sh:length(v)'。 –

+1

對不起,但我必須告訴你,那是錯誤的。只要重新考慮一下。 '1 3 5 7'是正確的索引 - 只要看看我的輸出矩陣顯然是正確的(長度爲5(即5列),你可以清楚地看到,這是塊大小cs = 5)和三個重疊條目每行的最後三個條目是下一行的三個第一條目) – tim

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 
+1

我不明白爲什麼這應該是必要的,特別是因爲錫要求一個沒有for循環的解決方案。 – tim

+1

@ bjoern:我同意丹尼斯的觀點,他的解決方案更簡單。 Arrayfun基本上也是一個for循環,在這種情況下甚至會明顯變慢。 – thewaywewalk

+0

@bjoern請注意,arrayfun幾乎只是一個循環的包裝(因此不會超越簡單的循環)。 –

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 - 就像輸入大小不適合一樣。在這種情況下,我生成第一個塊的索引,並添加每個塊的偏移量。由於一個輸入是行向量,另一個是列向量,因此結果是一個矩陣。最後,當用矩陣索引一個向量時,結果就是一個矩陣,這正是你所期望的。

它是一個單線,(幾乎)總是很有趣:)。

+0

用'CS = 5試試吧',會給你三個而不是兩個(二將作爲SH正確= 2)重疊項 – tim

+0

@bjoern正如我在你的問題的評論中提及,您的解決方案確實給出了不同的結果。但是,這並不意味着這是正確的。 –

+0

好的,現在我明白你在說什麼了。我100%確定'sh'描述了重疊條目的數量,但現在我看到你們都把它稱爲另一種措施。對不起我的錯,真的要有錯過了面向對象和我只是現在看到的是,該描述並不像貼例子唯一不明確 – tim

1

你有信號處理工具箱嗎?那麼命令是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,因爲columnwise是默認值。

+0

我喜歡使用這些小寶石,沒有人知道它已經在工具箱中。問題在於它可能會在最後一幀留下部分數據,但這取決於您想要實現的目標。 –

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。這是否根據需要處理所有情況?