forked from nipraxis/textbook
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex_reshape.Rmd
119 lines (96 loc) · 3.16 KB
/
index_reshape.Rmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
---
jupyter:
jupytext:
text_representation:
extension: .Rmd
format_name: rmarkdown
format_version: '1.2'
jupytext_version: 1.11.5
---
# Index ordering and reshape in NumPy and MATLAB
Let’s make a 3D array by taking a 1D array from 0 through 23, and filling the
3D array by depth (the last axis), and then by column (the second axis) and
then by row (the first axis):
```{python}
# Fill in a NumPy array
import numpy as np
numbers = np.arange(24)
py_arr = np.zeros((2, 3, 4))
n_index = 0 # Python has 0-based indices
for i in range(2): # row index changes slowest
for j in range(3): # then column index
for k in range(4): # depth index changes fastest
py_arr[i, j, k] = numbers[n_index];
n_index += 1
print(py_arr[:, :, 0])
print(py_arr[:, :, 1])
```
We can do the same thing in MATLAB, or its open-source version, Octave:
<!-- We previously did this live, with
.. runblock:: octave
>> % Fill in a MATLAB / Octave array
etc. But then we need octave for every build, which seemed a bit much. -->
```
>> % Fill in a MATLAB / Octave array
>> numbers = 0:23;
>> m_arr = zeros(2, 3, 4);
>> n_index = 1;
>> for i = 1:2 % row index changes slowest
for j = 1:3 % then column index
for k = 1:4 % depth index changes fastest
m_arr(i, j, k) = numbers(n_index);
n_index = n_index + 1;
end
end
end
>> m_arr(:, :, 1)
ans =
0 4 8
12 16 20
>> m_arr(:, :, 2)
ans =
1 5 9
13 17 21
```
Remember that MATLAB and Octave have 1-based indices. That is, the index to
the first element on an axis is 1. Python has 0-based indices. Given that,
these two arrays are the same. By “the same” I mean that that `m_arr[i, j,
k] == py_arr[i-1, j-1, k-1]` for any `i, j, k`. You can see this from the
printout above of the first two planes in each array in Python and MATLAB.
So far, we see that NumPy / Python and MATLAB indexing are the same, apart
from the 0-based / 1-based difference. They differ in their default way of
getting elements when doing a reshape.
When NumPy or MATLAB reshapes one array into another array, it takes the
elements from the first array in some order, and puts them into the new array
using the same order. The default order in NumPy is to take the elements off
the last axis first, then the second to last, back to the first axis. This is
the same order as the loop above:
```{python}
numbers = np.arange(24)
reshaped = np.reshape(numbers, (2, 3, 4))
# This is exactly the same as the original ``py_arr``
np.all(reshaped == py_arr)
```
MATLAB does a reshape using the opposite order, taking the elements off the
first axis first:
<!-- was:
.. runblock:: octave -->
```
>> m_reshaped = reshape(0:23, [2 3 4]);
>> m_reshaped(:, :, 1)
ans =
0 2 4
1 3 5
>> m_reshaped(:, :, 2)
ans =
6 8 10
7 9 11
```
If you prefer this ordering, you can ask NumPy to do the same, by using the
`order` parameter to `reshape`:
```{python}
# First axis first fetching, like MATLAB
first_1_reshaped = np.reshape(numbers, (2, 3, 4), order='F')
print(first_1_reshaped[:, :, 0])
print(first_1_reshaped[:, :, 1])
```