I currently have a 3 dimensional matrix and I want to extract a single row (into the third dimension) from it by index (say matrix(2,1,:)). I initially anticipated that the result of this would be a 1 dimensional matrix however what I got was a 1 by 1 by n matrix. Usually this wouldn't be a problem but some of the functions I'm using don't like 3D matrices. For example see the problem replicated below:
threeDeeMatrix=rand(3,3,3);
oneDeeAttempt=threeDeeMatrix(1,1,:);
norm(oneDeeAttempt)
Which returns the error message:
Error using norm
Input must be 2-D.
This is because oneDeeAttempt is
oneDeeAttempt(:,:,1) =
0.8400
oneDeeAttempt(:,:,2) =
0.0700
oneDeeAttempt(:,:,3) =
0.7663
rather than [0.8400 0.0700 0.7663]
How can I strip these extra dimensions? The only solution I can come up with is to use a loop to manually copy the values but that seems a little excessive.
Using permute to rearrange the matrix
The solution (which I found in the final stages of asking this) is to use permute which rearranges the order of the dimensions (similar to a=a' for 2D matrices). Once the unit dimensions are last they are stripped from the matrix and it becomes 1 dimensional.
oneDee=permute(oneDeeAttempt,[3 1 2]) %rearrange so the previous third dimension is now the first
%the matrix is now 3 by 1 by 1 which becomes 3
Using squeeze to remove leading singleton dimensions
As pointed out by Luis Mendo squeeze will very simply remove these leading singleton dimensions without having to worry about which dimensions are non singleton
oneDee=squeeze(oneDeeAttempt);
Related
A MATLAB array has an infinite number of trailing singleton dimension (theoretically).
So a 1x10 array is in fact a 1x10x1x1x1... array. I suppose that MATLAB just hides the trailing singleton dimension.
You can observe this behaviour with this code snippet:
permute([1:10],[2,1,4,3])
MATLAB deals with permuting the 3rd and 4th dimension without any problem even if it's a 1D array.
But why does MATLAB not hide the trailing singleton dimension in the 2nd dimension?
size(rand(10,1))
gives:
ans =
10 1
size(rand(10,1,1))
also gives:
ans =
10 1
Is that because MATLAB is optimized for linear algebra? So, is it simply a convention?
I have two vectors
A = [...] %size 1x320
B = [...] %size 1x192
I would like to combine the two vectors in one but the way I want to combine them is the following:
Take the first 5 elements of vector A then add 3 elements from vector B add the next 5 elements from vector A then add the next element from vector B and so on until the both vectors are combined in one. I think the process should be repeated 64 times since 320/5=64 and 192/3=64.
Is there any built-in Matlab function to do that?
I don't think that there is a built-in function that does exactly that, but the following will do what you want:
A=randi(10,1,320);
B=randi(10,1,192);
C=zeros(1,length(A)+length(B));
for i=1:5
C(i:8:end)=A(i:5:end);
end
for i=6:8
C(i:8:end)=B(i-5:3:end);
end
Then the array C is the combined array.
Edit: Another way to do that, without for loops:
A=randi(10,1,320);
B=randi(10,1,192);
A_new=reshape(A,5,[]);
B_new=reshape(B,3,[]);
C=[A_new;B_new];
C=reshape(C,[1,numel(C)]);
In this solution, by specifying the third parameter in reshape(A,5,[]) to be [], we allow it to adjust the number of columns according to the length of A, given that the number of rows in the reshaped array is 5. In addition, numel(C) is the total number of elements in the array C. So this solution can be easily generalized to higher number of arrays as well.
I have a string array:
size(entries)
ans =
1 19413
I would like to rearrange the array to 4853 rows and 4 columns:
output=permute(entries,[4853 4]);
but get following error:
Error using permute ORDER contains an invalid permutation index.
What is the (probably obvious thing) I am doing wrong? thanks
You currently have 19413 elements, yet you wish to reshape this into a 4853 x 4 matrix that consists of 4853 * 4 = 19412 elements. No function in the world will help you do this because the original and target amount of elements don't match - they're off by one element. If you remove one of the elements...say... the last one, then we're getting somewhere.
Supposing you made a mistake and included that extra element by accident, you don't use permute here, but you use reshape. The second argument to reshape is the amount of elements to spread out for each target dimension, and that's what you're looking for. First remove the extraneous element that appears at the end of the array, then reshape the matrix:
output = reshape(entries(1:end-1),[4853 4]);
I'm 3 years late, but here's to anyone still looking for an answer.
In your case as mentioned above, yes you should use reshape() while minding that you preserve the total number of elements.
You use permute() when you want to reorder the dimensionality of an n-dimensional (ND) matrix.
The ORDER parameter specifies the order of the columns.
For example, if matrix A is LxMxN, the following line would make it MxLxN.
A = permute(A,[2 1 3]);
Hope this clears things.
MATLAB is well-known for being column-major. Consequently, manipulating entries of an array that are in the same column is faster than manipulating entries that are on the same row.
In that case, why do so many built-in functions, such as linspace and logspace, output row vectors rather than column vectors? This seems to me like a de-optimization...
What, if any, is the rationale behind this design decision?
It is a good question. Here are some ideas...
My first thought was that in terms of performance and contiguous memory, it doesn't make a difference if it's a row or a column -- they are both contiguous in memory. For a multidimensional (>1D) array, it is correct that it is more efficient to index a whole column of the array (e.g. v(:,2)) rather than a row (e.g. v(2,:)) or other dimension because in the row (non-column) case it is not accessing elements that are contiguous in memory. However, for a row vector that is 1-by-N, the elements are contiguous because there is only one row, so it doesn't make a difference.
Second, it is simply easier to display row vectors in the Command Window, especially since it wraps the rows of long arrays. With a long column vector, you will be forced to scroll for much shorter arrays.
More thoughts...
Perhaps row vector output from linspace and logspace is just to be consistent with the fact that colon (essentially a tool for creating linearly spaced elements) makes a row:
>> 0:2:16
ans =
0 2 4 6 8 10 12 14 16
The choice was made at the beginning of time and that was that (maybe?).
Also, the convention for loop variables could be important. A row is necessary to define multiple iterations:
>> for k=1:5, k, end
k =
1
k =
2
k =
3
k =
4
k =
5
A column will be a single iteration with a non-scalar loop variable:
>> for k=(1:5)', k, end
k =
1
2
3
4
5
And maybe the outputs of linspace and logspace are commonly looped over. Maybe? :)
But, why loop over a row vector anyway? Well, as I say in my comments, it's not that a row vector is used for loops, it's that it loops through the columns of the loop expression. Meaning, with for v=M where M is a 2-by-3 matrix, there are 3 iterations, where v is a 2 element column vector in each iteration. This is actually a good design if you consider that this involves slicing the loop expression into columns (i.e. chunks of contiguous memory!).
In the code below "G" returns a (10*4) matrix which is in the correct orientation.
All I want then is to be able to view/call these (10*4) matrices indexed by (j,k). However when I store the matrix "G" in the 4-D matrix "test" the data is displayed in a way that is a little counter intuitive? When I look at test in the variable editor I get:
val(:,:,1,1) =
1
val(:,:,2,1) =
0
val(:,:,3,1) =
0
val(:,:,4,1) =
0
.
.
.
val(:,:,1,10) =
1
val(:,:,2,10) =
0
val(:,:,3,10) =
0
val(:,:,4,10) =
0
So all the data is there but I want it displayed at a 10*4 matrix?
Also as you will see I had to change the code for "Correl_betas" and transpose "G" to get to where I am above. However I felt I did this by playing around rather than what I thought the code should be doing. Why does the original code not work? I am having to change the order of the 3rd and 4th dimensions when declaring "Correl_betas" and then pass the transpose of G, but this seems totally counter intuitive as the last two dimensions in the original "Correl_betas" and the original (un-transposed) "G" also match? But when I did it this way the ordering seemed even further from the 10*$ matrix I want.
So I have 2 questions?
1.) How can I get to the 2-dimentional (10*4) matrices I want indexed by j,k from where I am?
2.) How come the original code above doesn't result in the last two columns producing (10,4) matrices?
A large part of the problem is that I have very little experience working with matrices that have more than 2 dimensions so sorry if this question shows a lack of understanding. Maybe a pointer to a god tutorial on how to interpret manipulate higher dimensional matrices would help too.
%Correl_betas=zeros(50,50,10,4);
Correl_betas=zeros(50,50,4,10);
mats=[1:10]';
L1=-1;
for j=1:51
L1=L1+1;
L2=-1;
for k=1:51
L2=L2+1;
lambda=[ L1; L2 ];
nObs=size(mats,1);
G= [ones(nObs,1) (1-exp(-mats./lambda(1)))./(mats./lambda(1)) ((1-exp(-mats./lambda(1)))./(mats./lambda(1))-exp(-mats./lambda(1))) ((1-exp(-mats./lambda(2)))./(mats./lambda(2))-exp(-mats./lambda(2)))];
%Correl_betas(j,k,:,:)=G;
Correl_betas(j,k,:,:)=G';
test=Correl_betas(j,k,:,:);
temp1=corrcoef(Correl_betas(j,k,:,2),Correl_betas(j,k,:,3),'rows','complete');
temp2=corrcoef(Correl_betas(j,k,:,2),Correl_betas(j,k,:,4),'rows','complete');
temp3=corrcoef(Correl_betas(j,k,:,3),Correl_betas(j,k,:,4),'rows','complete');
F2_F3(j,k)=temp1(1,2);
F2_F4(j,k)=temp2(1,2);
F3_F4(j,k)=temp3(1,2);
end
end
To reshape the matrix as desired,
val2 = permute(val,[4 3 2 1]);
This brings the 4th dimension (size of 10) onto the first, and the the 3rd dimension (size of 4) onto the second.
In your loop, both j and k cycle through 1:51 so the first two dimensions of Correl_betas will end up being length 51 too.