Determining Order of flattening an array using colons

조회 수: 32 (최근 30일)
Vassilis Lemonidis
Vassilis Lemonidis 2021년 9월 23일
편집: Vassilis Lemonidis 2021년 9월 23일
Hello, I need help understanding how Matlab applies flattening of arrays.
I know it uses a Fortran way of accessing information, so, given an N-D array, the dimension order that will change faster during eg. a reshape will be 1,2,3 etc. (and not N,N-1,N-2 etc as in C-manner). One would expect that, when one tries to reduce the dimensions of an array using colons, the reduction will be done in the same manner as the accessing. However this seems not to hold.
For example, we have an array A with dimensions (X,Y,Z). If we use A(:,:,:) we get the copy of the array. If we use A(:,:) we expect an array with dimensions (X*Y, Z), with the i,j element pointing at (i mod X, i div Y, j) element of A . However, no, what we get is an array (X, Y*Z), with the i,j element pointing at (i, j mod Y, j div Y) element of A. Why does this happen? Is it possible to determine/change this behavior?
Example:
x = cat(3,eye(3), eye(3), eye(3));
x(:,:)
ans =
1 0 0 1 0 0 1 0 0
0 1 0 0 1 0 0 1 0
0 0 1 0 0 1 0 0 1
whereas I would expect
1 1 1
0 0 0
0 0 0
0 0 0
1 1 1
0 0 0
0 0 0
0 0 0
1 1 1
same as when there is the 2 d analog
x = eye(3);
x(:)
1
0
0
0
1
0
0
0
1
  댓글 수: 1
Stephen23
Stephen23 2021년 9월 23일
편집: Stephen23 2021년 9월 23일
"However this seems not to hold."
It most certainly does hold! Lets try it. Your example 3D array:
format compact
x = cat(3,eye(3), eye(3), eye(3))
x =
x(:,:,1) = 1 0 0 0 1 0 0 0 1 x(:,:,2) = 1 0 0 0 1 0 0 0 1 x(:,:,3) = 1 0 0 0 1 0 0 0 1
has its elements stored in this order:
x(:) = 1:27
x =
x(:,:,1) = 1 4 7 2 5 8 3 6 9 x(:,:,2) = 10 13 16 11 14 17 12 15 18 x(:,:,3) = 19 22 25 20 23 26 21 24 27
Using two subscripts keeps exactly the same order (just as expected):
y = x(:,:)
y = 3×9
1 4 7 10 13 16 19 22 25 2 5 8 11 14 17 20 23 26 3 6 9 12 15 18 21 24 27
y(:) % absolutely no change in the order!
ans = 27×1
1 2 3 4 5 6 7 8 9 10
Your example appears to have the elements in exactly the same order, so it seems that you are mixing up the order of elements with the array size: whilst certainly related, these are not the same thing.

댓글을 달려면 로그인하십시오.

채택된 답변

Stephen23
Stephen23 2021년 9월 23일
편집: Stephen23 2021년 9월 23일
"If we use A(:,:) we expect an array with dimensions (X*Y, Z), with the i,j element pointing at (i mod X, i div Y, j) element of A"
No, we don't expect that at all.
In fact the last given index refers to that dimension and also to all infinite trailing dimensions. Your test-case is entirely consistent with that (and this paradigm also informs us that the concept of linear indexing is really just an edge-case of subscript indexing). So a general rule that describes both linear and subscript indexing is actually this:
A(dim1,dim2,..,dimN,ThisDimAndAllTrailingDim)
where N>=0.
And yes, it is documented here:
Loren writes: "Indexing with fewer indices than dimensions If the final dimension i<N, the right-hand dimensions collapse into the final dimension. E.g., if A = rand(1,3,4,1,7) and we type A(1,2,12), then we get the element as if A were reshaped to A(1,3,28) and then indexed into. 28 repesents the product of the final size of the final dimension addressed and the other "trailing" ones."
and she then proceeds to give a detailed example. Take a look!
"One would expect that, when one tries to reduce the dimensions of an array using colons, the reduction will be done in the same manner as the accessing."
It is.
" Is it possible to determine/change this behavior?"
I doubt that you would convince TMW to redesign this very simple indexing concept into your much more complicated concept that requires MOD and DIVISION and whatnot, but you can certainly try:
  댓글 수: 1
Vassilis Lemonidis
Vassilis Lemonidis 2021년 9월 23일
I see, so the notation is to be perceived as "freezing" early dimensions and squeezing the ones not included in the indexing, that makes sense. So, to see that the reduction is done in the same manner as the accessing, reshape(A, [], size(A,3)) gives out an (X*Y,Z) array and reshape(A, size(A,1), []) gives out a (X, Y*Z) array, the same as the one being produced by A(:,:) . With the third index missing, the former correspondence would seem more matching, under the Python/C way of thinking, but it is the latter one. Thus, through comparison, it indeed matches the Fortran way of accessing. Thank you for clearing this out to me. Nonetheless pretty complete and resourceful answer.

댓글을 달려면 로그인하십시오.

추가 답변 (1개)

Sulaymon Eshkabilov
Sulaymon Eshkabilov 2021년 9월 23일
How about this:
A = cat(3, eye(3), eye(3), eye(3))
B =reshape(A(:,:).',3,[])
  댓글 수: 1
Vassilis Lemonidis
Vassilis Lemonidis 2021년 9월 23일
Sure, thanks for the effort, but what I am seeking here is the reason behind what is happening, and whether this can be alleviated. Coming from a numpy environment, I face something that looks so ugly in implementation, and it makes no sense to me why. Is it speed? Is it something else? Can I change globally this behavior in my program? It does not make any mathematical sense.

댓글을 달려면 로그인하십시오.

카테고리

Help CenterFile Exchange에서 Matrix Indexing에 대해 자세히 알아보기

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by