For my project I need to save vectors in a matrix, thus creating a multidimensional array (3D-Matrix).
Now I'm wondering on how to access my vectors.
Lets say I have a lot of vectors stored in an array c. I could access all vectors with c(i,:).
I can also perform vector operations and use buit in fuctions like norm(c(1,:))and it gives me the absolute value of the vector. Everythings fine
Now if I store a vector v in a 2D-matrix M, i can still access every element of the vector, but M(i,j,:) doesnt give me the output [vx;vy;vz]I'm looking for. Instead matlab gives three outputs resulting in problems using the built in vector operations.
Is there any way around this?
Or do I have to implement my own functions to operate on a 3d-matrix?
Edit:
If z is a vector, the output is: z = [zx zy zz]
If this vetor is stored in a 2x2x3 matrix M(2,2,3), lets say in M(1,1), the output when accessing the vector by M(1,1,:)isnt [zx zy zz].
Instead the output is: M(:,:,1) = zx M(:,:,2) = zy M(:,:,3) = zz
Thanks for pointing out to change the direction the vector is stored in the matrix.
M(i,j,:) returns a 1×1×3 array, which Matlab understand is not exactly a vector v as you want, but a three-dimensional array, which happens to have only one element with respect to the first and second indices.
You can easily remove the dimensions of length 1 with the built-in function squeeze:
A = zeros(1,1,3);
A(:,:,1:3) = [1 2 3]
A =
A(:,:,1) =
1
A(:,:,2) =
2
A(:,:,3) =
3
B = squeeze(A)
B = 3×1
1
2
3
Related
Say A is a 3x4x5 array. I am given a vector a, say of dimension 2 and b of dimension 2. If I do A(a,b,:) it will give 5 matrices of dimensions 2x2. I instead want the piecewise vectors (without writing a for loop).
So, I want the two vectors of A which are given by (a's first element and b's first element) and (a's second element and b's second element)
How do I do this without a for loop? If A were two dimensions I could do this using sub2ind. I don't know how to access the entire vectors.
You can use sub2ind to find the linear index to the first element of each output vector: ind = sub2ind(size(A),a,b). To get the whole vectors, you can't do A(ind,:), because the : has to be the 3rd dimension. However, what you can do is reshape A to be 2D, collapsing the first two dimensions into one. We have a linear index to the vectors we want, that will correctly index the first dimension of this reshaped A:
% input:
A = rand(3,4,5);
a = [2,3];
b = [1,2];
% expected:
B = [squeeze(A(a(1),b(1),:)).';squeeze(A(a(2),b(2),:)).']
% solution:
ind = sub2ind(size(A),a,b);
C = reshape(A,[],size(A,3));
C = C(ind,:)
assert(isequal(B,C))
You can change a and b to be 3d arrays just like A and then the sub2ind should be able to index the whole matrix. Like this:
Edit: Someone pointed out a bug. I have changed it so that a correction gets added. The problem was that ind1, which should have had the index number for each desired element of A was only indexing the first "plane" of A. The fix is that for each additional "plane" in the z direction, the total number of elements in A in the previous "planes" must be added to the index.
A=rand(3,4,5);
a=[2,3];
b=[1,2];
a=repmat(a,1,1,size(A,3));
b=repmat(b,1,1,size(A,3));
ind1=sub2ind(size(A),a,b);
correction=(size(A,1)*size(A,2))*(0:size(A,3)-1);
correction=permute(correction,[3 1 2]);
ind1=ind1+repmat(correction,1,2,1);
out=A(ind1)
If I have a square matrix of arrays such as:
[1,2], [2,3]
[5,9], [1,4]
And I want to get the mean of the first values in the arrays of each row such:
1.5
3
Is this possible in Matlab?
I've used the mean(matrix, 2) command to do this with a matrix of single values, but I'm not sure how to extend this to deal with the arrays.
Get the first elements in all arrays of matrix, then call mean function
mean(matrix(:,:,1))
maybe you need to reshape before call mean
a = matrix(:,:,1);
mean(a(:))
You can apply mean function inside mean function to get the total mean value of the 2D array at index 1. You can do similary with array at index 2. Consider the following snapshot.
After staring at your problem for a long time, it looks like your input is a 3D matrix where each row of your formatting corresponds to a 2D matrix slice. Therefore, in proper MATLAB syntax, your matrix is actually:
M = cat(3, [1,2; 2,3], [5,9; 1,4]);
We thus get:
>> M = cat(3, [1,2; 2,3], [5,9; 1,4])
M(:,:,1) =
1 2
2 3
M(:,:,2) =
5 9
1 4
The first slice is the matrix [1,2; 2,3] and the second slice is [5,9; 1,4]. From what it looks like, you would like the mean of only the first column of every slice and return this as a single vector of values. Therefore, use the mean function and index into the first column for all rows and slices. This will unfortunately become a singleton 3D array so you'll need to squeeze out the singleton dimensions.
Without further ado:
O = squeeze(mean(M(:,1,:)))
We thus get:
>> O = squeeze(mean(M(:,1,:)))
O =
1.5000
3.0000
This question already has answers here:
Two arrays defining 2D coordinates, as array indices
(2 answers)
Closed 2 years ago.
I have X and Y positions for a large array and I would like to use them to define what the contents of that position. I could run a for loop to define the positions but I think there would be a faster method. I tried to use the array position define function.
x = [6,2,3]
y = [1,2,3]
c = [1,1,1,2,2,3;...
1,1,1,2,2,5;...
2,2,1,4,2,3;...
1,1,4,3,2,3;...
1,2,3,4,5,3;...
1,2,3,5,4,2];
When I type the equation above it results in the answer below
c(y,x)
ans =
1 2 3
1 1 1
2 2 1
What I'm looking for are the 1:1 positions from the arrays.
c(y(1),x(1))
c(y(2),x(2))
c(y(3),x(3))
Is there any way to limit the arrays to a linear sequence? my only guess right now is to reshape the arrays into a cell matrix containing the individual a and b and then perform a cellfun. but I think I'm making it to complicated.
You have to convert the locations into linear indices first, then you can grab the correct elements in the desired linear sequence. You can use sub2ind to help you do that:
ind = sub2ind(size(c), y, x); % Get linear indices
v = c(ind); % Get the elements
Doing this thus gives:
>> v = c(ind)
v =
3 1 1
You can verify for yourself that each pair of (y,x) gives you the right element you're looking for. For example, when y = 1 and x = 6, the element retrieved is 3 and so on.
(* I don't know programming in Matlab. It is just a general question about Matlab language. *)
In Excel, we can store a formula in a cell. For instance, if A2 contains a formula = A1+10, the re-evaluation of A2 returns 30 when the value of A1 is 20.
My question is, is there a similar mechanism in matlab? That said, can we specify a formula in a element of an array in Matlab, so that we can re-evaluate the array later?
Edit 1:
Following the comment of #rayryeng I try to make an example to illustrate the concept... Actually, this is exactly what spreadsheet languages such as Excel can do.
So my question is, is there a mechanism that permits the following in Matlab? (Note that the following syntax is just symbolic)
>> B = [1 2; B{1,1}+2 4] // store some values and a formula in the array
B =
1 2
3 4
>> B{1,1} = 10 // change the value of one cell
B =
10 2
3 4
>> EVAL(B) // there is a re-evaluation command to re-calculate all the cells
ans =
10 2
13 4
Hopefully I'm understanding what you want correctly, but the answer is indeed yes. You can store "formulas" in a cell array where each element is a handle or an anonymous function.
Perhaps you mean something like this:
formulae = {#(x) x+10, #sin, #cos, #(x) x / 3};
The syntax # denotes a function handle and the (x) denote that this is an anonymous function with the input variable x. The first cell element provides a function that adds 10 to every value that goes into it, the second and third parameters are handles to sin and cos, so these act like those trigonometric functions. The last handle divides every value that goes into it by 3.
To demonstrate, let's create a small array, then go through each formula and apply each of them to the small array:
>> formulae = {#(x) x+10, #sin, #cos, #(x) x / 3};
>> A = [1 2; 3 4]
A =
1 2
3 4
>> formulae{1}(A)
ans =
11 12
13 14
>> formulae{2}(A)
ans =
0.8415 0.9093
0.1411 -0.7568
>> formulae{3}(A)
ans =
0.5403 -0.4161
-0.9900 -0.6536
>> formulae{4}(A)
ans =
0.3333 0.6667
1.0000 1.3333
We first create the formulae, then create a small 2 x 2 matrix of [1 2; 3 4]. After, we access each formula's cell, then put in the input A into the function and we get what you see.
However, when you're starting out, start with actually declaring functions in function scripts.... don't use this kind of style of programming for practical applications. It makes your code less readable. For example, doing sin(A) is much more readable than formula{2}(A). People reading your code have to remember what position in the array corresponds to what formula you are applying to each element in the input.
Consider that I have a vector/array such that it looks as follows:
each part is a sub array of some size fixed and known size (that can only be accessed through indexing, i.e. its not a tensor nor a higher order array). So for example:
x1 = x(1:d);
if d is the size of each sub array. The size of each sub array is the same but it might vary depending on the current x we are considering. However, we do know n (the number of sub arrays) and d (the size of all of the sub arrays).
I know there is usually really strange but useful tricks in matlab to do things more optimized. Is there a way to extract those using maybe indexing and and make a matrix where the rows (or columns) are those parts? as in:
X = [x_1, ..., x_n]
the caveat is that n is a variable and we don't know aprior what it is. We can find what n is, but its not fixed.
I want to minimize the amount of for loops I actually write in matlab to hope its faster...just to add some more context.
First I would consider simple reshaping to keep the output as a simple double matrix
x = (1:15).' %'
d = 3;
out = reshape(x,d,[])
and further on just use indexing to access the columns out(:,idx);
There is no need to know n in advance, as reshape is calculating it based on d and the number of elements in x.
out =
1 4 7 10 13
2 5 8 11 14
3 6 9 12 15
If you'd insist on something like cell arrays, use accumarray with ceil to get the subs:
out = accumarray( ceil( (1:numel(x))/d ).', x(:), [], #(x) {x})