Search code examples
matlabmatrixsubmatrix

What is the rule behind the way singleton dimensions are squeezed in a submatrix?


It appears to me that MATLAB squeezes the singleton dimensions on the right-hand side of the last non-singleton dimension, with the restriction that a matrix must be at least two dimensional.

Inferring a rule from examples makes me feel uncomfortable, but it seems to work.

in 2D:

E = zeros(2,3);

E(1,:); % 1x3
E(:,1); % 2x1

in 3D:

E = zeros(2,3,4);

E(1,:,:); % 1x3x4
E(:,1,:); % 2x1x4
E(:,:,1); % 2x3

E(1,1,:); % 1x1x4
E(:,1,1); % 2x1
E(1,:,1); % 1x3

in 4D:

E = zeros(2,3,4,5);

E(:,:,:,1) % 2x3x4
E(:,:,1,1) % 2x3
E(:,1,1,1) % 2x1

E(1,:,:,:) % 1x3x4x5
E(1,1,:,:) % 1x1x4x5
E(1,1,1,:) % 1x1x1x5

E(:,:,1,:) % 2x3x1x5
E(:,1,:,:) % 2x1x4x5

E(1,:,:,1) % 1x3x4
E(1,:,1,:) % 1x3x1x5
E(:,1,:,1) % 2x1x4

E(1,1,:,1) % 1x1x4
E(1,:,1,1) % 1x3

Can anyone confirm whether this is the rule?

Incidental question: does this rule also apply to functions such as diff()? It seems like so.

The only difference I see is that you can get an empty matrix,then singleton dimensions on the left-hand side of the empty dimension are not removed, even when it is the greatest dimension:

E = zeros(2,3,4);

diff(E,1,1) % 1x3x4
diff(E,3,2) % 0x3x4

diff(E,2,2) % 2x1x4
diff(E,3,2) % 2x0x4

diff(E,3,3) % 2x3
diff(E,4,3) % 2x3x0

in 4D

E = zeros(2,3,1,5);
diff(E,3,4) % 2x3x1x2
diff(E,4,4) % 2x3
diff(E,5,4) % 2x3x1x0

Then again, this is just an ad hoc explanation and I am not going to test every possible case. What is the rule?


Solution

  • Any trailing singleton dimensions higher than the second are automatically stripped off. So 1x2x1 will automatically become 1x2, as will 1x2x1x1x1x1x1x1x1x1, but 2x1 remains 2x1. This happens when you index, like in your question, but also when a function like diff() would output something ending in singleton dimensions.

    Any singleton dimensions not being the last are left. Thus 1x2x1x1x1x2 remains 1x2x1x1x1x2, and 1x2x1x1x1x2x1x1 becomes 1x2x1x1x1x2 as well. You can force the squeeze() to force all singleton dimensions out; you'll always be left with at least a 2D matrix though (even if it is just a 1x1 scalar).


    As a sidenote, as Cris Lunego said,

    But then try this: E = zeros(2,3); size(E,3)! Each array actually has an infinite number of singleton dimensions at the end!

    So technically each array has an infinite number of dimensions, with the last ones all being empty, and MATLAB not showing them by default, but they are indexable:

    A = rand(3,3);
    A(2,2,1)
    ans =
        0.4854
    A(2,2,1,1)
    ans =
        0.4854
    
    size(A)
    ans =
         3     3
    size(A,4)
    ans =
         1