【问题标题】:Create matrix by repeatedly overlapping a vector通过重复重叠向量来创建矩阵
【发布时间】:2012-10-19 02:24:58
【问题描述】:

我很难在 MATLAB 中编写以下代码: 假设你有以下向量:

a   
b
c
d
e
f
g
h
...

指定(偶数)窗口大小,创建以下维度矩阵 L 行 x n 列(例如,L = 4):

a c e ...
b d f ...
c e g ...
d f h ...

更困难的是获取任意长度的向量,指定窗口的数量,并优化(最大化)窗口大小,以便转储向量末尾的更少值。

【问题讨论】:

  • 窗口位置是否总是在列之间移动 2?还是基于窗口大小?或者它是一个额外的输入?您还可以澄清一下“向量末尾的值被转储”是什么意思吗?谢谢!
  • 窗口位置移动 L/2。前任。窗口大小 L = 8,移位 4。指定窗口大小 L。前任。如果向量的长度为 9 并且 L 设置为 4,则只能重叠 3 次:{a b c d} {c d e f} {e f g h} {i}(这个值 i 被转储,因为无法再有一个完整的窗口形成)
  • 提供的任何答案对您有用吗?如果是这样,请花时间接受(并可能投票)最好的(在您看来)答案。这将激励人们在未来帮助您。

标签: matlab vector matrix vectorization


【解决方案1】:

在向量中创建索引矩阵。对于 L=4(我假设您与 L/2 重叠),索引为 [1,2,3,4;3,4,5,6;5,6,7,8] 等。令 x = 1 :L, y = L/2, 索引向量为x+0y,x+1y,x+2y,以此类推。

% let your initial data be in vector "data"
L = 4
N = floor(length(data)/(L/2))-1 % number of windows, or you specify this
mi = repmat(1:L,[N,1]) + repmat((L/2) * (0:(N-1))',[1,L]) % x + y * 0,1,2...
out = data(mi) % out is N-by-L, transpose to L-by-N if you like

【讨论】:

  • 如果您只是切换 x 和 y 的定义以匹配问题中的输出格式,我会更喜欢这个答案。
  • @BrianL 我只是倾向于将较长的维度放在首位。切换输出的维度就像 out = out' 一样简单,或者让最后一行 out = data(mi)'。
【解决方案2】:

简答

bsxfun 在这种情况下是你的朋友。以下单线(假设您知道Lv 是您的向量)可以满足您的需求

v(bsxfun(@plus, [0:L-1]', 1:L/2:numel(v)-L))

说明

要尝试并理解它,让我们进一步看看。这个想法是首先创建一个向量来确定窗口在v 向量中的起始位置。 Windows 启动每个L/2 条目(L 是偶数,所以我们可以划分)。但是有多少个窗户适合?我们可以依靠 MATLAB 来解决这个问题:

start_offset = 1:L/2:numel(v)-L;

这里我们只需要指定

  • 第一个窗口位于索引 1
  • windows 每L/2 条目启动一次
  • 最后一个窗口应该开始在 v 向量结束之前至少 L 个条目。这样最后一个窗口就在里面了。

现在,示例的其余部分:

v = 'a':'z';
L = 4;

% indices in every output matrix column are contiguous
% and the difference between first and last is `L-1`
id1 = [0:L-1]';

% start_offset determines where in the input vector v every window starts.
% windows start every L/2 entries. The last entry that fits will start
% at some index, from which we can still use L subsequent indices to access v
start_offset = 1:L/2:numel(v)-L;

% calculate how many entries were dropped from v
% from number of elements in v subtract the largest index value used
dropped = numel(v) - (start_offset+L-1);

% window indices are created using bsxfun and singleton expansion.
% Every window's indices are given by [0:L-1] + window start index
idx = bsxfun(@plus, id1, start_offset);

v(x)

ans =

  acegikmoqsu
  bdfhjlnprtv
  cegikmoqsuw
  dfhjlnprtvx

【讨论】:

    【解决方案3】:

    这里有一个通用的方法来做你想做的事:

    1) 计算合适的窗口宽度(以及相应的移位)
    2) 通过从 1 迭代您希望将窗口每列移动的量,确定每列的起始索引,直到最终值。将其设为行向量。
    3) 使用bsxfun 将其扩展为索引矩阵。
    4) 使用索引从原始向量中获取值。

    vec = 1:17; #% original data vector
    num_windows = 3; #% specified number of windows
    possible_window_length = 1:length(vec);
    window_length = possible_window_length(find(possible_window_length +...
        (num_windows-1) * possible_window_length/2 < length(vec),1,'last'));
    window_shift = floor(window_length)/2;
    window_length = window_shift * 2; #% calculated window length
    max_final_start_index = (length(vec)-window_length+1);
    start_indices = 1:window_shift:max_final_start_index;
    inds = bsxfun(@plus,start_indices,(0:window_length-1)');
    soln = vec(inds); #% get the solution
    num_excluded_vals = max_final_start_index - start_indices(end)
    disp(soln);
    num_excluded_vals =  1
    disp(soln);
        1    5    9
        2    6   10
        3    7   11
        4    8   12
        5    9   13
        6   10   14
        7   11   15
        8   12   16
    

    【讨论】:

      【解决方案4】:

      在 MATLAB 中有很多方法可以通过操作索引、过程方法、矢量化解决方案等来实现这一点。但是,如果 MATLAB 对函数式编程风格。本着这种精神,我提出以下解决方案。确保在定义时这些变量中没有任何值。

      take=@(mat,n)mat(1:n)
      partition=@(mat,L)cell2mat(arrayfun(@(x)take(circshift(mat(:),-x*L/2),L),...
              0:fix((length(mat)-L)/2+1)-1,'UniformOutput',0))
      

      现在用一个测试向量试试:

      partition(1:10,4)
      
       %ans = 
       %    1     3     5     7
       %    2     4     6     8
       %    3     5     7     9
       %    4     6     8    10
      

      上述解决方案在分割后丢弃向量末尾不适合长度L 的最终值。您现在可以在此基础上处理其他安排,并找出最佳窗口长度以最大限度地减少最终浪费等。

      【讨论】:

        猜你喜欢
        • 2021-08-08
        • 1970-01-01
        • 1970-01-01
        • 2012-09-04
        • 1970-01-01
        • 1970-01-01
        • 2011-06-02
        • 1970-01-01
        • 2016-06-03
        相关资源
        最近更新 更多