Cant figure out the "reshape" function

조회 수: 31 (최근 30일)
Tim Johansson
Tim Johansson 2021년 3월 24일
댓글: Sean de Wolski 2021년 3월 24일
I've got a signal recorded across 8 channels, that i want to segment into epochs.
i want to segment this into 89 epochs of 190 samples across the 8 channels
However, the reshape function does not keep the structure of the signal. Everything seems to be thrown around with cylindrical data looking like this:
And the first epoch like this:
I would expect the rows to be identical, but they are for some reason i cant figure out not.
My code looks like this:
CylindricalEpochs = reshape(Cylindrical,190, 8, 89);
Can anyone shine a light on what i'm doing wrong?
Thanks in advance
  댓글 수: 1
Sean de Wolski
Sean de Wolski 2021년 3월 24일
Just wanted to say - this is a model question for how to ask a question here :)

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

답변 (2개)

Walter Roberson
Walter Roberson 2021년 3월 24일
Computer memory is linear. There is no such thing as physical 2D addressing in any computer you are likely to encounter; I haven't used a computer with dual index fields since about 1987 (and those instructions were seldom used by compilers, as they were noticably slower.)
When you see a 2D array in any modern computer, it is almost certain that the 2D array was implemented in one of four ways:
  1. A 2D array starts out with a column of memory pointers, and each of the pointers refers to a row of consecutive memory. 2D indexing is by using the first index to refer to the row of pointers, pulling out one, and then the second index is the offset from the beginning of that pointer. The strips for the row do not have to be near each other in memory -- the strip for row 3 might be hundreds of megabytes away from the strip for row 2. This is a common arrangement.
  2. A 2D array starts out with a row of memory pointers, and each of the pointers refers to a column of consecutive memory. This is the same kind of arrangement as the one above, just sort of turned on its side. Again, the strips for the columns do not have to be near each other. This is not a common arrangement, but it is possible.
  3. A 2D array is just a bunch of consecutive memory. The second index (column number) is multiplied by the length of the column, and the first index (row number) is added, giving the address of an individual location in memory. Values that are in adjacent rows in the same column are beside each other in memory, and when the bottom of a column is reached, the next value in memory is the one associated with the top of the next column. This is a common arrangement, and it is what MATLAB uses. This is called "Row Major" arrays: consecutive addresses in memory sweep down rows.
  4. A 2D array is just a bunch of consecutive memory. The first index (row number) is multiplied by the length of the row, and the second index (column number) is added, giving the address of an individual location in memory. Values that are in adjacent columns in the same row are beside each other in memory, and when the right side of a row is reached, the next value in memory is the one associated with the beginning of the next row. This is a common arrangement. This is called "Column Major" arrays: consecutive addresses in memory sweep across columns.
So, with your 16910 x 8 array, MATLAB first stores all 16910 entries from column 1, then right below them, all 16910 entries from column 2, and so on with the last chunk being the 16910 entries from column 3.
When you reshape(), MATLAB does not change the order of any entries: it just internally relables how large the rows and columns are. So for example if you had
A11 A12
A21 A22
A31 A32
then the memory order would be
A11
A21
A31
A12
A22
A32
then if you reshape() it from 3 x 2 into 2 x 3, then the order in memory stays exactly the same, and you would get
A11 A31 A22
A21 A12 A32
-- read the order from the top left towards the bottom, head right to the next column, and so on, and you will see that the memory order has not changed.
This is what reshape() does: leaves the order in memory alone but calls it a different size (that has the same total number of elements.)
But that is not what you want to do in your case.
In order to know how to get the order you want, you need to know whether the order of your data in memory is 89 related data values, with 190 groups of that, and 8 columns across, or if the order of your data in memory is 190 related data values, with 89 groups of that, and 8 columns across.
Your "first epoch" has a height of 190 rows, so we can speculate that what you have in memory
Ep1R1C1 to Ep1R1C8
Ep1R2C1 to EP1R2C8
to
Ep1R190C1 to Ep1R190C8
"virtual gap"
Ep2R1C1 to Ep2R1C8
Ep2R2C1 to Ep2R2C8
to
Ep2R190C1 to EP2R190C8
"virtual gap"
Ep3R1C1 (and so on)
up to
Ep89R190C1 to Ep89R190C8
If so, then what you would need to get 190 rows per epoch x 8 columns x 89 epochs, would be to reorder some of the data in memory. You would do that with a combination of reshape() and permute()
CylindricalEpochs = permute(reshape(Cylindrical, 190, 89, 8), [1 3 2]);
This first moves to 190 rows x 89 columns by 8 planes, which by examination of the above description of how memory addressing works, would show you that the in-memory order is the same: the top of the second column would be the item in-memory after the bottom of the first column, and the bottom of the first (new) column is Ep1R190C1, the next entry in-memory is Ep2R1C1, and the reshape() moves that up to the top of a column of its own. This step is like folding up the data rather than changing where a single thing is relative to the beginning of the array.
Then the second part, permute(), does change where thing are in memory. permute() [1 3 2] moves entries around so that the first dimension (length 190) is left the same (each column of an individual epoch continues to be a column), but reorders between columns and planes. It is like
for column = 1:89
for plane = 1 : 8
CE(:,plane,column) = Ep(:,column,plane);
end
end
CE ends up 190 x 8 x 89, data having been moved from 190 x 89 x 8.

Steven Lord
Steven Lord 2021년 3월 24일
As others have said, reshape reshapes the data in the array down columns then across rows and out pages.
A = 1:24;
B = reshape(A, [3 4 2])
B =
B(:,:,1) = 1 4 7 10 2 5 8 11 3 6 9 12 B(:,:,2) = 13 16 19 22 14 17 20 23 15 18 21 24
If you want to go across rows first then down columns and out pages, reshape and permute the array.
C = reshape(A, [4 3 2])
C =
C(:,:,1) = 1 5 9 2 6 10 3 7 11 4 8 12 C(:,:,2) = 13 17 21 14 18 22 15 19 23 16 20 24
D = permute(C, [2 1 3])
D =
D(:,:,1) = 1 2 3 4 5 6 7 8 9 10 11 12 D(:,:,2) = 13 14 15 16 17 18 19 20 21 22 23 24

카테고리

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