Let's say I have a non-empty vector z.
I would like to replicate and shape this vector into a matrix with dimensions [r, c, length(z)].
For example:
z = 1:5;
r = 3;
c = 3;
I am looking for a function that gives me:
ans(:, :, 1) =
[ 1 1 1 ]
[ 1 1 1 ]
[ 1 1 1 ]
ans(:, :, 2) =
[ 2 2 2 ]
[ 2 2 2 ]
[ 2 2 2 ]
...
ans(:, :, 5) =
[ 5 5 5 ]
[ 5 5 5 ]
[ 5 5 5 ]
NOTE:
Doing something like
tmp = zeros(r,c,length(z));
tmp = repmat(z, 3, 3, 1);
doesn't work. Instead it returns a 15x15 matrix as
tmp =
[ 1:5, 1:5, 1:5 ]
[ 1:5, 1:5, 1:5 ]
[ 1:5, 1:5, 1:5 ]
which is not what I want.
Transposing z first doesn't work either.
The only solution I know is to initially set z to be the 3rd dimension of a vector:
z(1,1,:) = 1:5;
Is there more efficient way to do this? Or is this the most effective approach?
COROLLARY: Is there a "transpose"-like function that transposes a vector into singleton dimension? That is, if transpose() shapes row vectors into column vectors and vice versa, is there a function that shapes a row/column vector into singleton dimensions and back?
Thanks in advance!
First permute the vector so that it's a single 3D vector, then use repmat:
z = permute(1:5, [1 3 2]);
r = 3; c = 3;
out = repmat(z, [r c]);
We get:
>> out
out(:,:,1) =
1 1 1
1 1 1
1 1 1
out(:,:,2) =
2 2 2
2 2 2
2 2 2
out(:,:,3) =
3 3 3
3 3 3
3 3 3
out(:,:,4) =
4 4 4
4 4 4
4 4 4
out(:,:,5) =
5 5 5
5 5 5
5 5 5
permute works by shuffling the dimensions of the input vector around. What we're doing here is that we are switching the column values so that they appear in slices of a single 3D vector. We then replicate this 3D vector for as many rows and as many columns as you want.
If permute is confusing, then assuming z hasn't been allocated, you can also do this:
z(1,1,:) = 1:5;
You can then go ahead and use this z with the same repmat syntax that I talked about before.
You can generate that using ndgrid
z = 1:5;
r = 3;
c = 3;
[~,~,out]=ndgrid(1:r,1:c,z)
or using bsxfun and permute
out = bsxfun(#plus,permute(z,[3,1,2]),zeros(r,c));
Related
I am trying to get a 4 dimentional matrix out of a vector and then reset it's
'lower triangel'.
for example, if my original vector is two dimentional: A = [1 2]' then I would like my initial matrix to be:
C(:,:,1,1) = [1*1*1*1 1*1*1*2 ; 1*1*2*1 1*1*2*2] = [ 1 2 ; 2 4]
C(:,:,2,1) = [2*1*1*1 2*1*1*2 ; 2*1*2*1 2*1*2*2] = [ 2 4 ; 4 8]
C(:,:,1,2) = [1*2*1*1 1*2*1*2 ; 1*2*2*1 1*2*2*2] = [ 2 4 ; 4 8]
C(:,:,2,2) = [2*2*1*1 2*2*1*2 ; 2*2*2*1 2*2*2*2] = [ 4 8 ; 8 16]
So C is:
C(:,:,1,1) = [ 1 2 ; 2 4] C(:,:,2,1) = [ 2 4 ; 4 8]
C(:,:,1,2) = [ 2 4 ; 4 8] C(:,:,2,2) = [ 4 8 ; 8 16]
and after reset I would like it to be:
C(:,:,1,1) = [ 1 2 ; 2 4] C(:,:,2,1) = [ 0 0 ; 0 0]
C(:,:,1,2) = [ 0 0 ; 4 8] C(:,:,2,2) = [ 0 0 ; 8 16]
shotrly, I want no rows repetitions.
I tried the following code:
A = [1 2]';
C = bsxfun(#times, permute(C, [4 3 2 1]), C*C');
disp('C before reset is:');
disp(C);
for k = 2:size(C, 4)
C(1:k-1,:,k) = 0;
end
disp('C after reset is:');
disp(C);
disp('The size of C is:');
disp(size(C));
But the output is:
BB before reset is:
(:,:,1,1) =
1 2
2 4
(:,:,1,2) =
2 4
4 8
C after reset is:
(:,:,1,1) =
1 2
2 4
(:,:,1,2) =
0 0
4 8
The size of BB is:
2 2 1 2
What did I miss?
I think I don't understand what is behind the line:
C = bsxfun(#times, permute(C, [4 3 2 1]), C*C');
what is the meaning of each number in the row [4 3 2 1]?
Thanks!
edit note: The matrix represents correlations between neurons. I am trying to look at the correlation structure of groups of 4 neurons. So, each 4 neurons sould only be measuresd once. I think that he matrix before reset contains 4! times, every group of 4, because they apear in all orders. I could leave it like this but I am think it might slow the program..
Permute exchanges dimensions, so for example
C = [1:3;4:6];
permute(C, [2 1])
Computes a simple transpose by swapping rows and columns. The [2 1] argument means that the 2st and 1st dimension of C are mapped to the 1st and 2nd dimension in the result. Each 'new' dimension is specified in order. So [3 2 1] would take the 3rd, 2nd and 1st dimensions to be the new 1st, 2nd and 3rd dimensions.
permute(C, [3 2 1])
ans =
ans(:,:,1) =
1 2 3
ans(:,:,2) =
4 5 6
Elements of C with row = 1 are found in where the 3rd dimension = 1 in the result. Similarly, elements of C with row = 2 are found where the 3rd dimension = 2 in the result.
Elements of C with column = 1 are still found where column = 1 in the result (and so on) as the column dimension was mapped to itself.
The rows of the result is the interesting dimension, it is singleton (i.e. there is only one row) as a result of C having no 3rd dimension.
Addressing the first part of your problem, the correct output for C can be obtained by
A = [1 2]'*[1 2];
C = bsxfun(#times, permute(A, [4,3,1,2]), A);
I would need more information on what you want the final behaviour to be ('resetting the lower triangle') as it is unclear to me what you desire.
A function that might be useful to you is the triu function which extracts upper triangular components of a matrix.
I have a matrix that I'd like to create a new ordering of, for example,
vals = [1 2; 3 4]
I also have two matrices, new_x and new_y such that new_x(a,b) = j and new_x(a,b) = k means that I want the value at vals (a,b) to be mapped to new_vals(j,k).
For example, given
new_x = [1 2; 2 1]
new_y = [2 2; 1 1]
I'd want
new_vals = [4 3; 1 2]
I understand that I could just write two for loops to build the new array, but matlab is notoriously good at providing operations on entire matricies. My question is, how would I build new_vals without the for loops?
Basically you are trying to get a matrix that when indexed with new_x and new_y would give us vals, i.e. -
output(new_x(1,1),new_y(1,1)) must be equal to vals(1,1),
output(new_x(1,2),new_y(1,2)) must be equal to vals(1,2) and so on.
We will try to verify this later on. For now, here's one solution using linear indexing -
nrows = size(vals,1); %// Store number of rows
%// Calculate linear indices
idx = (new_x + (new_y-1)*nrows);
%// Trace/map back to sorted version of "1:numel(vals)"
[~,traced_back_idx] = sort(idx(:));
%// Index into vals with traced back linear indices & then reshape & transpose
out = reshape(vals(traced_back_idx),[],nrows).'
Here's another and possibly faster way -
out = nan(size(vals));
out((new_x + (new_y-1)*nrows)) = vals;
out = out.'
As discussed earlier for verification, let's index into out with new_x and new_y and that should match up with vals. Here's a code to do so -
for ii = 1:size(out,1)
for jj = 1:size(out,2)
check_back(ii,jj) = out(new_y(ii,jj),new_x(ii,jj));
end
end
Sample runs -
Case #1 (sample from question):
vals =
1 2
3 4
new_x =
1 2
2 1
new_y =
2 2
1 1
new_vals =
4 3
1 2
out =
4 3
1 2
check_back = (must be same as vals)
1 2
3 4
Case #2:
vals =
1 2 5
3 4 5
6 8 3
new_x =
1 2 3
3 1 2
3 2 1
new_y =
2 2 3
2 1 1
1 3 3
out =
4 5 6
1 2 3
3 8 5
check_back = (must be same as vals)
1 2 5
3 4 5
6 8 3
I think i see what you are trying to do here. new_x and new_y are just coordinates for the new_val matrix rigth? The problem is tha what you are trying to do only works for vectors, not for matrix, so the only way is to transform the matrix into a vector, reorder the values and then go back to matrix like:
vals = [1 ,2; 3, 4];
A=reshape(vals,1,4); % A is a vector [ 1 3 2 4]
new_coord=[2,3,4,1];
B(new_c)=A; %B is [4 1 3 2]
new_val=reshape(B,2,2) %back to matrix
Obtainig new_val=[4 3; 1 2]. Also B=A(new_c) is also allowed but with different coordinates, eventhoug is much easy to think the rigth coordinates in that way.
I am sure there must be a way to include the new_x matrix and transform everything into new_coord
I have a vector v = [1 2 3 4 5 6 ] and I want to convert it to the matrix [1 2 ; 3 4 ; 5 6] meaning that each two adjacent indices become a row. But when I use
A = reshape(v, [], 2) I get A = [1 4 ; 2 5 ; 3 6]
Is there a MATLAB function that does that?
Use reshape to create the transposed matrix, then transpose it to get what you want:
reshape(v,2,[]).'
I'm learning Matlab and I see a line that I don't understand:
A=[x; y']
What does it mean? ' usually means the transponate but I don't know what ; means in the vector. Can you help me?
The [ ] indicates create a matrix.
The ; indicates that the first vector is on the first line, and that the second one is on the second line.
The ' indicates the transponate.
Exemple :
>> x = [1,2,3,4]
x =
1 2 3 4
>> y = [5;6;7;8]
y =
5
6
7
8
>> y'
ans =
5 6 7 8
>> A = [x;y']
A =
1 2 3 4
5 6 7 8
[x y] means horizontal cat of the vectors, while [x;y] means vertical.
For example (Horizontal cat):
x = [1
2
3];
y = [4
5
6];
[x y] = [1 4
2 5
3 6];
(Vertical cat):
x = [1 2 3];
y = [4 5 6];
[x; y] =
[1 2 3;
4 5 6];
Just to be clear, in MATLAB ' is the complex conjugate transpose. If you want the non-conjugating transpose, you should use .'.
It indicates the end of a row when creating a matrix from other matrices.
For example
X = [1 2];
Y = [3,4]';
A = [X; Y']
gives a matrix
A = [ 1 2 ]
[ 3 4 ]
This is called vertical concatenation which basically means forming a matrix in row by row fashion from other matrices (like the example above). And yes you are right about ' indicating the transpose operator. As another example you could use it to create a transposed vector as follows
Y = [1 2 3 4 5];
X = [1; 2; 3; 4; 5];
Y = Y';
Comparing the above you will see that X is now equal to Y. Hope this helps.
Let set the size of x m*n (m rows and n columns) and the size of y n*p.
Then A is the matrix formed by the vertical concatenation of x and the transpose of y (operator '), and its size is (m+p)*n. The horizontal concatenation is done with comma instead of semi-column.
This notation is a nice shorthand for function vertcat.
See http://www.mathworks.fr/help/techdoc/math/f1-84864.html for more information
The semicolon ' ; ' is used to start a new row.
e.g. x=[1 2 3; 4 5 6; 7 8 9] means
x= 1 2 3
4 5 6
7 8 9
So if u take x=[1 2 3; 4 5 6] and y=[7 8 9]'
then z=[x; y'] means
z= 1 2 3
4 5 6
7 8 9
I have a matrix, for example
A = [ 1 2 3; 4 5 6; 7 8 9] ;
and a vector of size 1x3 which specifies which element in each row is the one I'm looking for - i.e. If
vector = [ 1 2 1 ]
then the desired output is
[ 1 5 7 ]
since 1 is the 1'st element in the 1'st row, 5 is the 2'nd in the 2'nd row, and 7 is the 1'st element in the 3'rd row.
How do I achieve this? Couldn't find a built in function to do this, which surprised me.
MATLAB provides the SUB2IND function to convert rows/columns subscripts to linear indices:
>> A = [1 2 3; 4 5 6; 7 8 9];
>> idx = sub2ind(size(A),1:3,[1 2 1]); %# rows: [1 2 3], cols: [1 2 1]
>> A(idx)
1 5 7
First of all, the indexes in Matlab go from top to bottom.
So in your case A[1] = 1 , A[2] = 4 , A[3] = 7
That said, it would be easier to work on A' , because its a bit more trivial.
B = A';
B((vector + [0:2].* 3))
It's a bit ugly, but diag(A(1:3,[1 2 1])) will do the trick.
Here's a variation of Yochai's answer but without the transpose (this is also basically what SUB2IND does in Amro's answer):
output = A((1:3)+3.*(vector-1));
Or for an array A of an arbitrary size:
nRows = size(A,1);
output = A((1:nRows)+nRows.*(vector-1));