Reputation: 2314
Is there a way to do the following?
I would like to turn a MATLAB array:
>> (1:10)'
ans =
1
2
3
4
5
6
7
8
9
10
Into the following sequential matrix (I am not sure what is the name for this):
ans =
NaN NaN NaN 1
NaN NaN NaN 2
NaN NaN NaN 3
1 2 3 4
2 3 4 5
3 4 5 6
4 5 6 7
5 6 7 8
6 7 8 9
7 8 9 10
I am able to do this, with the following function, but it iterates over each row and it is slow:
function V = vec2stack(X, num_sequences)
n = numel(X);
len_out = n - num_sequences + 1;
V = zeros(len_out,num_sequences);
for kk = 1:len_out
V(kk,:) = X(kk:kk +num_sequences - 1)';
end
V = [nan(num_sequences,num_sequences); V(1:end-1,:)];
end
X = 1:10;
AA = vec2stack(X,3)
Running the above function for a vector of length 1,000,000 takes about 1 second, which is not fast enough for my purposes,
tic;
Lag = vec2stack(1:1000000,5);
toc;
Elapsed time is 1.217854 seconds.
Upvotes: 2
Views: 154
Reputation: 25490
You can use repmat()
to repeat the X vector horizontally. Then, notice that each column is one more than the previous. You can add a row-vector that has the same number of columns as the matrix, and Matlab will broadcast the vector onto the entire matrix and do the addition for you.
In older versions of Matlab, you might need to explicitly repmat()
the row vector to get the shapes to match.
function V = vec2stack(X, num_sequences)
% Repeat X, 1 time vertically, num_seq times horizontally
% X(:) ensures it's a column vector so we have the correct shape
mat = repmat(X(:), 1, num_sequences);
% make a row vector from 0:num_sequences-1
vec = 0:(num_sequences-1);
% or explicitly repmat on vec if you need to:
% vec = repmat(0:(num_sequences-1), numel(X), 1);
% Add the two. Matlab broadcasts the row vector onto the matrix
% Because they have the same number of columns
mat = mat + vec;
% Build the return matrix
V = [nan(num_sequences, num_sequences); mat];
end
X = (1:10)';
AA = vec2stack(X,3)
% You can easily add the last column as another column
Testing speedon Octave Online:
%% Loopy version
tic;
Lag = vec2stack(1:1000000,5);
toc;
Elapsed time is 17.4092 seconds
%% Vectorized version
tic;
Lag = vec2stack((1:1000000)',5);
toc;
Elapsed time is 0.110762 seconds.
~150x speedup. Pretty cool!
Upvotes: 2