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
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
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.
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))
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
L/2
entriesNow, 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
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