MATLAB Answers

Adam
0

Working with 1d vector sequences

Asked by Adam
on 19 Nov 2019 at 17:20
Latest activity Commented on by the cyclist
on 19 Nov 2019 at 19:44
This is a problem I seem to come up against quite often in Matlab and have never really found a good solution to. Maybe there isn't one since it is a matrix-based language in essence.
As we all know, the lowest dimensionality for a variable in Matlab is 2d, meaning that what we would call a vector in other languages has to be explicitlty a row (1,n) or a column (n,1).
I do a lot of signal processing and frankly I don't care if my data is a row or a column, I just want to manipulate it as a sequence and move it along to the next part of the program.
The problem is that my sequences are created in various places, from various sources and so inevitably they sometimes end up as a column and sometimes as a row. And I have never found a neat way of dealing with this.
For example, my current problem is that I have a sequence and I need to pad it to a specific length. Conceptually this is simple - I work out the difference in length, half it and put zeros of that number at the start and end. But whilst I know my sequence is 1d (i.e. isvector returns true) I don't know at this point, for sure if it is a column or a row. I can create my zeros for padding using size( mySequence ) and replacing the non-singleton with the padding size, though that is still messy, but then I have to concatenate anyway and I know no way of simply telling Matlab 'concatenate these 1d sequences in the obvious way'. I have to do either horzcat or vertcat, meaning an ugly if statement, or I can use cat( dim, ... ) but I still have to acquire the index of the non-singleton dimension.
So am I missing something? Does someone have a nice neat way to solve the following problem
"Given a 1d sequence, pad the sequence symmetrically with 0s (adding excess at the end if required) and return it in whatever orientation it was originally"?
This is the 'best' I have come up with, but it's not exactly neat!
% Support either one of these
mySequence = rand( 12,1 );
% mySequence = rand( 1, 13 );
targetLength = 25;
sequenceLength = numel( mySequence );
nonSingletonDim = find( size( mySequence) ~= 1, 1 ); % It's fine to assume here that the sequence is a vector of one or other type
padding = ( targetLength - sequenceLength ) / 2;
prePadSize = size( mySequence );
prePadSize( nonSingletonDim ) = floor( padding );
postPadSize = prePadSize;
postPadSize( nonSingletonDim ) = ceil( padding );
result = cat( nonSingletonDim, zeros( prePadSize ), mySequence, zeros( postPadSize ) );

  2 Comments

Adam
on 19 Nov 2019 at 17:30
Of course, there is always the "bull in a china shop" approach:
if isrow( mySequence )
result = [ zeros( 1, floor( padding ) ), mySequence, zeros( 1, ceil( padding ) ) ];
else
result = [ zeros( floor( padding ), 1 ); mySequence; zeros( ceil( padding ), 1 ) ];
end
and it is arguably neater than trying to be fancy! It's just frustrating to have to resort to this kind of thing all over the code, for different purposes.
You can turn your sequencies to the column (or row, if you prefer) vectors at the very beginning by, e.g.:
mySequence = reshape ( mySequence , numel(mySequence) , 1);
or
mySequence = reshape ( mySequence , 1 , numel(mySequence));
and work with the column (row) vectors throghout.
Alternatively, you can check at the beginning if it is the column (or row) vector and transpose it if it is not, and write the rest of the code for the chosen version; you can introdice a key pointing to a need of a back transpose at the end if needed.

Sign in to comment.

2 Answers

Answer by the cyclist
on 19 Nov 2019 at 17:53

v = v(:);
will be a column vector regardless of whether it came in as a row or column vector. So, you could "pre-process" your vectors with that step.

  1 Comment

Adam
on 19 Nov 2019 at 18:02
That is another approach, but to do that I need to first store a boolean telling me if it was a row or a column initially and then put it back as I found it because it isn't acceptable for something to pass in a row vector and have a padded column-vector returned. Whatever function called this is expecting that it will have its sequence just padded, not arbitrarily transposed. Where it is using the sequence it might matter whether it is a row or a column, just that here (and in many other places I work), I have a basic sequence-type function to apply that doesn't care and should respect whatever orientation was passed to it.

Sign in to comment.


Answer by the cyclist
on 19 Nov 2019 at 19:34
Edited by the cyclist
on 19 Nov 2019 at 19:35

Still fairly brute-force, but here is a little function that will pad a row or column vector, retaining the orientation:
function outvec = padRowOrColVec(invec,n)
outvec = [[invec zeros(isrow(invec),n)]; zeros(n,iscolumn(invec))];
end
Example of calling syntax:
v = rand(3,1);
padRowOrColVec(v,4)
It relies on "padding" with an empty vector in the wrong dimension, based on the output of the isrow and iscolumn commands.

  1 Comment

the cyclist
on 19 Nov 2019 at 19:44
This solution gives a warning that indicates that this use might not work in future versions. It's not immediately clear to me how to rejigger the algorithm to avoid that.

Sign in to comment.