Creating a matrix by repeatedly overlapping a vector

It is very difficult for me to code the following in MATLAB: Suppose you have the following vector:

ab c d e f g h ... 

To set the window size (even), create the following size matrix L rows with columns n (example, L = 4 ):

 ace ... bdf ... ceg ... dfh ... 

It is even more difficult to take a vector of arbitrary length by specifying the number of windows and optimize (maximize) the size of the window in order to reset fewer values ​​at the end of the vector.

+4
source share
4 answers

Create an index matrix in your vector. For L = 4 (I assume that you overlap on 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 index vector is x + 0y, x + 1y, x + 2y, etc.

 % 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 
+4
source

Short answer

bsxfun is your friend in this case. The following single-line (if you know that L and v are your vector) does what you want

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

Explanation

To try and understand this, let's look further. The idea is to first create a vector defining where the windows start in vector v . Windows launches every L/2 element ( L even, so we can split). But how many windows are suitable? We can rely on MATLAB to figure this out by saying:

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

Here we just need to indicate that

  • the first window is at index 1
  • windows fire each L/2 element
  • in the last window, at least L records must begin before the end of the vector v. So the last fist of the window is there.

Now the remaining 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 indices are given by [0:L-1] + window start index idx = bsxfun(@plus, id1, start_offset); v(x) ans = acegikmoqsu bdfhjlnprtv cegikmoqsuw dfhjlnprtvx 
+4
source

Here is a general way to do what you want:

1) Calculate the appropriate window width (and the corresponding offset)
2) Define the starting indices of each column, iterating from 1 by the amount you want to shift the window in each column to the final value. Make this line vector.
3) Use bsxfun to expand this to the index matrix.
4) Use indexes to get 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 
+2
source

MATLAB has many ways to do this by manipulating indexes, procedural approaches, vectorized solutions, etc. However, I cannot help but think about how simple some tasks can be if MATLAB had a little support for a functional programming style. In this spirit, I present the following solution. Make sure that you do not yet have values ​​in these variables during the definition.

 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 using 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 do not correspond to the length L after the section. Now you can expand it to process other devices and determine the optimal window lengths for minimal time loss, etc.

+1
source

Source: https://habr.com/ru/post/1440681/


All Articles