【问题标题】:matlab: dividing vector into overlapping chunks of fixed sizematlab:将向量划分为固定大小的重叠块
【发布时间】:2014-01-03 18:30:47
【问题描述】:

我有一个向量,我想将其拆分为大小为cs 的重叠子向量,以sh 为单位。想象一下输入向量是:

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

给定 chunksize 为 4 (cs=4) 和 shift 为 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 中,我发现了如何做到这一点,但在考虑非重叠子向量时。

【问题讨论】:

    标签: matlab vector split range indices


    【解决方案1】:

    这个呢?首先,我根据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 &gt; 0;sh &lt; cssh &lt; 0 如果您想在两者之间保留一些值,理论上是可能的。

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

    【讨论】:

    • 我为什么要这样做?它也适用于不同的数字。 idx 只应该给我子向量的起始索引,因此我定义。需要 cs-sh 作为步骤 - 编辑:我尝试使用不同的向量和不同数量的 cssh 并且效果很好。
    • 对于cs=5; sh=3,我假设起始索引是1 4 7,而不是1 3 5 7。如果是这种情况,可以使用idx=1:sh:length(v)
    • 抱歉,我得告诉你,这是错误的。只是重新考虑一下。 1 3 5 7 是正确的索引 - 只需看看我的输出矩阵,它显然是正确的(您可以清楚地看到长度为 5(即 5 列),即 chunksize cs=5)和三个重叠条目(最后三个条目每行是下一行的前三个条目)
    【解决方案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
    

    【讨论】:

    • 我不明白为什么这是必要的,尤其是当 Tin 要求没有for-loop 的解决方案时。
    • @bjoern:我同意丹尼斯的观点,他的解决方案更简单。 Arrayfun 基本上也是一个 for 循环,在这种情况下甚至更慢。
    • 丹尼斯,我认为你的代码仍然有错误 -> v(t-3:t); 这应该是什么?我的意思是其中缺少关于 cs 的内容,现在您总是获取 3 个错误的条目
    • 这也是我第一次更改以纠正它,但它仍然有问题,cs = 5; sh = 2; 给了我矩阵中的三个重叠条目,而不是 2
    • @DennisJaheruddin:我认为您计算块数的方式不正确,请参阅我的答案。您仅根据sh 计算要为myMat 预分配的行数,同时还应包括cs。对于cs = 10sh = 2,它应该只产生 2 行,而在你的情况下它预分配 5 行。
    【解决方案3】:

    您可以通过以下方式使用函数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 的功能。在这种情况下,我生成第一个块的索引,并添加每个块的偏移量。由于一个输入是行向量,另一个是列向量,因此结果是一个矩阵。最后,当使用矩阵索引向量时,结果是一个矩阵,这正是您所期望的。

    而且它是单行的,(几乎)总是很有趣:)。

    【讨论】:

    • cs = 5;sh = 2; 试试,会给你三个而不是两个(两个是正确的,因为 sh=2)重叠条目
    • @bjoern 正如我在对您的问题的评论中提到的,您的解决方案确实给出了不同的结果。但是,这并不一定意味着它是正确的。
    • 好的,现在我明白你指的是什么了。我 100% 确定 sh 描述了重叠条目的数量,但现在我看到你们都将其称为另一种衡量标准。对不起,我的错,真的一定错过了哦,我现在才看到描述不是唯一的,因为发布的例子是模棱两可的
    • one-liner bsxfun(几乎)总是值得 +1!
    【解决方案4】:

    您有信号处理工具箱吗?那么命令是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,因为默认是按列排列的。

    【讨论】:

    • 我喜欢使用这些没有人知道它已经在工具箱中的小宝石。问题是它可能会在最后一帧中留下部分数据,但这取决于您想要实现的目标。
    【解决方案5】:

    您可以通过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 的新行。这会根据需要处理所有情况吗?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-12-11
      • 2011-04-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多