Create matrix by repeatedly overlapping a vector

前端 未结 4 2041
再見小時候
再見小時候 2021-01-19 20:52

I\'m having great difficulty coding the following in MATLAB: Suppose you have the following vector:

a   
b
c
d
e
f
g
h
...

Specifying an (e

相关标签:
4条回答
  • 2021-01-19 21:13

    Create the matrix of indices into your vector. For L=4 (I assume you are overlapping by L/2), the indices are [1,2,3,4;3,4,5,6;5,6,7,8] etc. Let x = 1:L, y = L/2, the vector of indices is x+0y,x+1y,x+2y, and so on.

    % 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
    
    0 讨论(0)
  • 2021-01-19 21:13

    There are many ways to do this in MATLAB by manipulating indices, procedural approaches, vectorized solutions, etc. Yet, I can't help but think of how simple some tasks might be, if MATLAB had a wee bit of support for functional style of programming. In that spirit, I present the following solution. Ensure that you don't already have any values in those variables at definition time.

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

    Now try it with a test vector:

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

    The above solution discards the final values at the end of the vector that don't fit a length L after partition. You can now build up on this to handle other arrangements and figure out optimal window lengths for minimal end wastage, etc.

    0 讨论(0)
  • 2021-01-19 21:32

    Short answer

    bsxfun is your friend in this case. The following one-liner (assuming you know L and v is your vector) does what you want

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

    Explanation

    To try it out and understand it, lets have a further look. The idea is to first create a vector that determines, where the windows start in the v vector. Windows start every L/2 entries (L is even, so we can divide). But how many windows fit? We can rely on MATLAB to figure this out by saying:

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

    Here we just only need to specify that

    • first window is at at index 1
    • windows start every L/2 entries
    • the last window should start at least L entries before the end of the v vector. So that the last window fist in there.

    Now, the rest of the example:

    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
    
    0 讨论(0)
  • 2021-01-19 21:33

    Here's a general way to do what you want:

    1) Calculate the appropriate window width (and corresponding shift)
    2) Determine the start indices of each column by iterating from 1 by the amount you want to shift the window each column, up to the final value. Make this a row vector.
    3) Use bsxfun to expand this to a matrix of indices.
    4) Use the indices to get the values from the original vector.

    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
    
    0 讨论(0)
提交回复
热议问题