Matlab: Vectorize the transpose in one step? [duplicate] - matlab

This question already has an answer here:
effective way of transformation from 2D to 1D vector
(1 answer)
Closed 9 years ago.
I would like to use the (:) operator and the transpose at the same time. Is this possible? Basically I would like to do something like
output = A'(:)
except that this does not work. Does anyone know a workaround?
Thanks!
Immo

The : operator in this case is shorthand for reshaping the matrix into a vector. You can work around the limitation of where you use the operator by using the reshape function explicitly:
octave> A = [1 2;3 4]
A =
1 2
3 4
octave> B=A'
B =
1 3
2 4
octave> C=B(:)
C =
1
2
3
4
octave> D=reshape(A',[],1) #% vectorize transpose in one line
D =
1
2
3
4

Try with:
output = reshape( A.', numel(A), 1);
>> A = rand(4,3);
>> output = reshape( A.', numel(A), 1);
A =
0.447213 0.046896 0.679087
0.903294 0.768745 0.651481
0.701071 0.122534 0.611390
0.535844 0.478595 0.772810
output =
0.447213
0.046896
0.679087
0.903294
0.768745
0.651481
0.701071
0.122534
0.611390
0.535844
0.478595
0.772810
Beware that reshape reads the matrices accessing along columns so you may not need to transpose the matrix A.
Also, remember that the operator ' is the hermitian operator, namely, conjugated of the transposed, whereas .' is simply transposition, which you could also get by transpose(A).
You may want to do everything in a single line without re-typing all every time. One solution is creating a function handles as boop:
>> boop = #(x) reshape( transpose(x), numel(x), 1)
>> output = boop(A)
output =
0.447213
0.046896
0.679087
0.903294
0.768745
0.651481
0.701071
0.122534
0.611390
0.535844
0.478595
0.772810

Related

Matrix generation from a vector

I have a column vector A. When A is a scalar I can use the colon operator to generate a vector like so
B = A-m:n:A+p
However, what I want to do is different. I want the result B to look like so,
[A-m, A-m+1 ... A ... , A+n-1, A+n]
I know I can accomplish this by using repmat on -m:n:p followed with a bsxfun added with the original A matrix.
Is there a more direct method?
If you just want to copy a handful instances of column vector v, you can always use
B = [v, v, v, ... v];
Or for row vector
B = [v ; v ; v ; ... v];
One easy vectorized way is this:
NewMatrix = diag(A)*ones(length(A),m+n+1) + ones(length(A),m+n+1)*diag(-m:1:n)
not a one-liner...
>> a=[1;2];
>> r=3:2:10;
>> repmat(a,1,size(r,2))+repmat(r,size(a,1),1)
ans =
4 6 8 10
5 7 9 11

Transpose of a vector without builtin MATLAB command

Does any one know how I can convert a row vector [6 8 2] into a column vector without using a builtin command. I would like to do it without for loop.A ny idea please. Some one asked me is it a home work I say no, it's part of my work. I am trying to convert MATLAB code to vhdl using hdl coder but hdl coder seems not supporting transpose function.
Some options:
R = 1:10; %// A row vector
%// using built-in transpose
C = R'; %'// be warned this finds the complex conjugate
C = R.'; %'// Just swaps the rows and columns
C = transpose(R);
%// Flattening with the colon operator
C = R(:); %// usually the best option as it also convert columns to columns...
%// Using reshape
C = reshape(R,[],1);
%// Using permute
C = permute(R, [2,1]);
%// Via pre-allocation
C = zeros(numel(R),1);
C(1:end) = R(1:end);
%// Or explicitly using a for loop (note that you really should pre-allocate using zeros for this method as well
C = zeros(numel(R),1); %// technically optional but has a major performance impact
for k = 1:numel(R)
C(k,1) = R(k); %// If you preallocated then C(k)=R(k) will work too
end
%// A silly matrix multiplication method
C = diag(ones(numel(R),1)*R)
You can use the (:) trick
t = [1 2 3];
t(:)
ans =
1
2
3
UPDATE: you should use this method only in the following case: you have a vector (not matrix) and want to make sure it is a column-vector. This method is useful, when you don't know what type (column, row) of vector a variable has.
Check this out
t = [1 2 3]'; %// column vector
t(:)
ans =
1
2
3
However
A=magic(3);
A(:)
ans =
8
3
4
1
5
9
6
7
2

visualizing 2D-graphs of n-dim. array via surf() in matlab

I want to show 2dim. Surface plots for different combinations of 2 parameters of a 3- or higher-dimensional array in matlab. The data for the non-shown dimensions are integrated (i.e. summed in the remaining dimensions). I am using surf(), and for parameter combinations other than (1,2) (eg. (1,3), (2,3) ...) I have to rearrange the data matrices in order to make it work.
I am looking for an alternative command (or shorter code) which does this work.
Here's the code:
a=zeros(3,3,2);
a(:,:,1) = [1 2 3 ;4 5 6; 7 8 9; 10 11 12]; % // data matrix
a(:,:,2) = -[1 2 3 ;4 5 6; 7 8 9; 10 11 12]*2; % // data matrix
ai=[[1 2 3 4]' [5 6 7 0]' [8 9 0 0]']; % // parameter vector
mat12 = sum(a,3);
surf(ai(1:3,2),ai(1:4,1),mat12)
aux13 = sum(a,2);
for i = 1:2; mat13(:,i) = aux13(:,:,i);
surf(ai(1:2,3),ai(1:4,1),mat13)
aux23 = sum(a,1);
for i = 1:2; mat23(i,:) = aux23(:,:,i);
surf(ai(1:3,2),ai(1:2,3),mat23)
In other words, I am looking for a way to use surf for matrices mat13 and mat23 without the aux13, aux23 variables and the for loop.
First your example doesn't run because you declare a=zeros(3,3,2); as a matrix [3x3x2] but you immediately try to populate it as a [4x3x2] matrix, so I had to adjust your first line to: a=zeros(4,3,2);
If I run your code with that adjustment, your auxiliary variable and for loops are to reform/reshape a matrix stripped of it's singleton dimension. Matlab provide a handy function for that : squeeze.
For example, your variable aux13 is of dimension [4x1x2], then mat13=squeeze(aux13); achieve the same thing than your for loop. Your matrix mat13 is now of dimension [4x2].
Since no for loop is needed, you can completely bypass your auxiliary variable by calling squeeze directly on the result of your summation: mat13=squeeze( sum(a,2) );
Full example, the code below does exactly the same than your code sample:
mat12 = sum(a,3);
surf(ai(1:3,2),ai(1:4,1),mat12)
mat13 = squeeze( sum(a,2) ) ;
surf(ai(1:2,3),ai(1:4,1),mat13)
mat23 = squeeze( sum(a,1) ) ;
mat23 = mat23.' ; %'// <= note the "transpose" operation here
surf(ai(1:3,2),ai(1:2,3),mat23)
Note that I had to transpose mat23 to make it match the one in your example.
sum(a,1) is [1x3x2] => squeeze that and you obtain a [3x2] matrix but your code arrange the same values in a [2x3] matrix, so the use of the transpose. The transpose operator has a shorthand notation .'.
I used it in the example in a separate line just to highlight it. Once understood you can simply write the full operation in one line:
mat23 = squeeze(sum(a,1)).' ;
The way you write your loops isn't exactly MATLAB syntax. Below is the correct loop syntax shown.
On line 2 and 3, you are trying to load (4x3)-matrices into (3x3)-matrices. That is why you get a subscript error. You could resolve it by making the zeros-matrix bigger. Here's some Syntax fixed:
a=zeros(4,3,2);
a(:,:,1) = [1 2 3 ;4 5 6; 7 8 9; 10 11 12]; % // data matrix
a(:,:,2) = -[1 2 3 ;4 5 6; 7 8 9; 10 11 12]*2; % // data matrix
ai=[[1 2 3 4]' [5 6 7 0]' [8 9 0 0]']; % // parameter vector
mat12 = sum(a,3);
surf(ai(1:3,2),ai(1:4,1),mat12)
aux13 = sum(a,2);
for i = 1:2 mat13(:,i) = aux13(:,:,i);
surf(ai(1:2,3),ai(1:4,1),mat13)
end
aux23 = sum(a,1);
for i = 1:2 mat23(i,:) = aux23(:,:,i);
surf(ai(1:3,2),ai(1:2,3),mat23)
end
Now, what are you exactly trying to do inside those loops?

Recurring Function with Matrix Input

I believe most functions in MATLAB should be able to receive matrix input and return the output in the form of matrix.
For example sqrt([1 4 9]) would return [1 2 3].
However, when I tried this recurring factorial function:
function k = fact(z)
if z ~= 0
k = z * fact(z-1);
else
k = 1;
end
end
It works perfectly when a number is input into fact. However, when a matrix is input into fact, it returns the matrix itself, without performing the factorial function.
E.g.
fact(3) returns 6
fact([1 2 3]) returns [1 2 3] instead of [1 2 6].
Any help is appreciated. Thank you very much!
Since MATLAB is not known to be good with recursive functions, how about a vectorized approach? Try this for a vector input -
mat1 = repmat([1:max(z)],[numel(z) 1])
mat1(bsxfun(#gt,1:max(z),z'))=1
output1 = prod(mat1,2)
Sample run -
z =
1 2 7
output1 =
1
2
5040
For the sake of answering your original question, here's the annoying loopy code for a vector or 2D matrix as input -
function k1 = fact1(z1)
k1 = zeros(size(z1));
for ii = 1:size(z1,1)
for jj = 1:size(z1,2)
z = z1(ii,jj);
if z ~= 0
k1(ii,jj) = z .* fact1(z-1);
else
k1(ii,jj) = 1;
end
end
end
return
Sample run -
>> fact1([1 2 7;3 2 1])
ans =
1 2 5040
6 2 1
You can use the gamma function to compute the factorial without recursion:
function k = fact(z)
k = gamma(z+1);
Example:
>> fact([1 2 3 4])
ans =
1 2 6 24
Not sure if all of you know, but there is an actual factorial function defined in MATLAB that can take in arrays / matrices of any size, and computes the factorial element-wise. For example:
k = factorial([1 2 3 4; 5 6 7 8])
k =
1 2 6 24
120 720 5040 40320
Even though this post is looking for a recursive implementation, and Divakar has provided a solution, I'd still like to put my two cents in and suggest an alternative. Also, let's say that we don't have access to factorial, and we want to compute this from first principles. What I would personally do is create a cell array that's the same size as the input matrix, but each element in this cell array would be a linear index array from 1 up to the number defined for each location in the original matrix. You would then apply prod to each cell element to compute the factorial. A precondition is that no number is less than 1, and that all elements are integers. As such:
z1 = ... ; %// Define input matrix here
z1_matr = arrayfun(#(x) 1:x, z1, 'uni', 0);
out = cellfun(#prod, z1_matr);
If z1 = [1 2 3 4; 5 6 7 8];, from my previous example, we get the same output with the above code:
out =
1 2 6 24
120 720 5040 40320
This will obviously be slower as there is an arrayfun then cellfun call immediately after, but I figured I'd add another method for the sake of just adding in another method :) Not sure how constructive this is, but I figured I'd add my own method and join Divakar and Luis Mendo :)

Doing operations between subsequent elements without using a FOR loop?

In Matlab, Is it possible to do simple operations between subsequent elements of an array without using a for loop? Something like diff(). For example, I have this vector:
A = [2 4 8 16 32]
and I want each element to be divided by its predecessor:
ans = [2 2 2 2]
How can I do it without going through all elements (without using loops)?
You can use the fact that division in Matlab work on both scalars and matrices, if you use the ./ operator rather than /
>> A = [2 4 8 16 32];
>> A(2:end) ./ A(1:end-1)
ans =
2 2 2 2
Regarding your question about doing dot() between vectors stored in the rows of a matrix. There is an additional argument to dot() that tells it whether your vectors are stored in columns (the default) or rows;
>> x = rand(3);
>> y = rand(3); # random vectors
>> dot(x,y) # dot product of column vectors
ans =
0.5504 0.5561 0.5615
>> dot(x,y,2) # dot product of row vectors
ans =
0.3170
1.0938
0.2572
Most functions in Matlab are vectorized so that they can work on scalars, vectors and matrices, but you sometimes have the read the documentation (e.g. type help dot) to work out how to use them.