I want to reduce a two dimensional matrix to row vector.
But using reshape with large matrices is really slow. The other alternative is to use colon, but i want matrix's transpose to be colon and not the matrix itself.
e.g.
A=magic(3)
A =
8 1 6
3 5 7
4 9 2
A(:) will stack up all the columns one by one. but i am looking for something like this:
AA=A(2:3,:)';
and then reshape or colon AA instead of A.
The issue is i dont want to define additional variable like AA.
Is there anyway to reduce dimension of two dimensional matrix without reshape?
You can avoid the additional variable by linear indexing. For your example:
A([2 5 8 3 6 9])
which gives
3 5 7 4 9 2
What's happening here is that you treat A as if it was already transformed into a vector, and the elements of this one-dimensional array are accessed through indices 1 through 9. Using the colon is a special case of linear indexing, A(:) is the same as A(1 : end).
Figuring out the right linear indices can be tricky, but sub2ind can help with that.
It is possible that this slightly speeds up the code, mainly because (as #Shai wrote) you avoid writing data to an intermediate variable. I wouldn't expect too much, though.
Try looking at subsref. For your example, you could use it as follows:
subsref(A',struct('type','()','subs',{{2:3,':'}}))
Update: I misunderstood the original question; I thought the OP wanted to select rows from 2:3 from the transposed A matrix keeping the columns as is. I will keep the previous answer in case it could be useful to others.
I think he/she could use the following to slice and flatten a matrix:
subsref(A(2:3,:)', struct('type','()','subs',{{':'}}))
This would give as output:
[3 5 7 4 9 2]'
Related
In something which made me spent several hours, I have found an inconsistency in how Matlab deals with dimensions. I somebody can explain to me OR indicate me how to report this to Matlab, please enlight me.
For size, ones,zeros,mean, std, and most every other old and common commands existing inside Matlab, the dimension arrangement is like the classical one and like the intended standard (as per the size of every dimension), the first dimension is along the column vector, the second dimension is along the row vector, and the following are the non graphical following indexes.
>x(:,:,1)=[1 2 3 4;5 6 7 8];
>x(:,:,2)=[9 10 11 12;13 14 15 16];
>m=mean(x,1)
m(:,:,1) = 3 4 5 6
m(:,:,2) = 11 12 13 14
m=mean(x,2)
m(:,:,1) =
2.5000
6.5000
m(:,:,2) =
10.5000
14.5000
m=mean(x,3)
m = 5 6 7 8
9 10 11 12
d=size(m)
d = 2 4 2
However, for graphical commands like stream3,streamline and others relying on the meshgrid output format, the dimensions 1 and 2 are swapped!: the first dimension is the row vector and the second dimension is the column vector, and the following (third) is the non graphical index.
> [x,y]=meshgrid(1:2,1:3)
x = 1 2
1 2
1 2
y = 1 1
2 2
3 3
Then, for stream3 to operate with classically arranged matrices, we should use permute(XXX,[2 1 3]) at every 3D argument:
xyz=stream3(permute(x,[2 1 3]),permute(y,[2 1 3]),permute(z,[2 1 3])...
,permute(u,[2 1 3]),permute(v,[2 1 3]),permute(w,[2 1 3])...
,xs,ys,zs);
If anybody can explain why this happens, and can indicate to me why this is not a bug, welcome.
This behavior is not a bug because it is clearly documented as the intended behavior: https://www.mathworks.com/help/matlab/ref/meshgrid.html. Specifically:
[X,Y,Z]= meshgrid(x,y,z) returns 3-D grid coordinates defined by the vectors x, y, and z. The grid represented by X, Y, and Z has size length(y)-by-length(x)-by-length(z).
Without speaking to the original authors, the exact motivation may be a bit obscure, but I suspect it has to do with the fact that the y-axis is generally associated with the rows of an image, while x is the columns.
Columns are either "j" or "x" in the documentation, rows are either "i" or "y".
Some functions deal with spatial coordinates. The documentation will refer to "x, y, z". These functions will thus take column values before row values as input arguments.
Some functions deal with array indices. The documentation will refer to "i, j" (or sometimes "i1, i2, i3, ..., in", or using specific names instead of "i" before the dimension number). These functions will thus take row values before column values as input arguments.
Yes, this can be confusing. But if you pay attention to the names of the variables in the documentation, you will quickly figure out the right order.
With meshgrid in particular, if the "x, y, ..." order of arguments is confusing, use ndgrid instead, which takes arguments in array indexing order.
I have a 3D matrix that each page/slice is independent of other slices. Thus, I would like to use the find command to filter my data in each page. However, when applied, find will return the indices in a row vector that describe my data as a whole, where actually it is not. For example:
a=rand(1,10,5);
ind=find(a<0.3);
This would return ind something like:
ind=
1 2 5 9 10 11 20 24 25 ...
I expected something like:
ind(:,:,1)=
1 2 3
ind(:,:,2)=
1 5 6 10 %based on each slice, independent to other slices
I intended to do so (independently), so that I could apply the found indices to each slice of other matrix.
Can this be done without using loop? Thanks in advance!
Use ind2sub() to convert your indices to subscripts. Something like this should work for a 3d array:
[i,j,k] = ind2sub(size(a), ind)
That said, the outputs (i, j, k), will all be the same size, that is the same size as ind. In other words, it gives one set of subscripts (i,j,k) (coordinates) for each value of a<0.3.
It's not completely clear what output you want/expect from your question, but if you want separate subscripts for each page in a, you'll have to filter further (e.g. j(i==1),k(i==1) for the first page in i).
I have this little problem and I hope that you can help me.
My question is about if there is someway to make this operation in MATLAB:
Suppose this matrix called A(4x3):
A=[1 2 3;4 5 6;7 8 9;8 9 1];
and this vector array called B (4x1):
B=[1;3;5;0];
Now the operation that I want to make is kinda simple: A+B=C, where C is:
A + B = C
C=[2 3 4;7 8 9;12 13 14;8 9 1];
As you can see, the first row of the matrix C is the sum between the first row of matrix A with the first value of the vector B, and it continues.
I know how to make it easily using a "for" but I want to know if there's a way to make it faster.
bsxfun [Apply element-by-element binary operation to two arrays with singleton expansion enabled] with a function handle #plus might just work for you. It lets B expand onto the second dimension as needed for operating with A which is already a 2D matrix and thus giving you the desired "summation" output -
bsxfun(#plus,A,B)
In MATLAB, we can operate on both rows and columns of a matrix. What does it exactly mean by "row major" or "column major"?
It is important to understand that MATLAB stores data in column-major order, so you know what happens when you apply the colon operator without any commas:
>> M = magic(3)
M =
8 1 6
3 5 7
4 9 2
>> M(:)
ans =
8
3
4
1
5
9
6
7
2
I tend to think "MATLAB goes down, then across". This makes it easy to reshape and permute arrays without scrambling your data. It's also necessary in order to grasp linear indexing (e.g. M(4)).
For example, a common way to obtain a column vector inline from some expression that generates an array is:
reshape(<array expression>,[],1)
As with (:) this stacks all the columns on top of each other into single column vector, for all data in any higher dimensions.
But this nifty syntactic trick lets you avoid an extra line of code.
In MATLAB, arrays are stored in column major order.
It means that when you have a multi-dimensional array, its 1D representation in memory is such that leftmost indices change faster.
It's called column major order because for a 2D array (matrix), the first (leftmost) index is typically the row index, so since it changes faster than the second (next to the right) index, the 1D representation of the matrix is memory correspond to the concatenation of the columns of the matrix.
I am trying to copy a few elements from a matrix, but not a whole row, and not a single element.
For example, in the following matrix:
a = 1 2
3 4
5 6
7 8
9 0
How would I copy out just the following data?
b = 1
3
5
i.e. rows 1:3 in column 1 only... I know that you can remove an entire column like this:
b = a(:,1)
... and I appreciate that could just do this and then dump the last two rows, but I'd like to use more streamlined code as I am running a very resource-intensive solution.
Elements in a matrix in MATLAB are stored in column-major order. Which means, you could even use a single index and say:
b = a(1:3);
Since the first 3 elements ARE 1,3,5. Similarly, a(6) is 2, a(7) is 4 etc. Look at the sub2ind method to understand more:
http://www.mathworks.com/help/techdoc/ref/sub2ind.html
You are not "removing" the second column, you are referencing the other column.
You should read some of the Matlab docs, they provide some help about the syntax for accessing portions of matrices:
http://www.mathworks.com/help/techdoc/learn_matlab/f2-12841.html#f2-428