Pretty much what the title says. I've read the documentation and I've played with the function for a while now but I can't discern what the physical manifestation of this transformation is.
问题:
回答1:
Computer memory is addressed linearly. Each memory cell corresponds to a number. A block of memory can be addressed in terms of a base, which is the memory address of its first element, and the item index. For example, assuming the base address is 10,000:
item index 0 1 2 3
memory address 10,000 10,001 10,002 10,003
To store multi-dimensional blocks, their geometry must somehow be made to fit into linear memory. In C
and NumPy
, this is done row-by-row. A 2D example would be:
| 0 1 2 3
--+------------------------
0 | 0 1 2 3
1 | 4 5 6 7
2 | 8 9 10 11
So, for example, in this 3-by-4 block the 2D index (1, 2)
would correspond to the linear index 6
which is 1 x 4 + 2
.
unravel_index
does the inverse. Given a linear index, it computes the corresponding ND
index. Since this depends on the block dimensions, these also have to be passed. So, in our example, we can get the original 2D index (1, 2)
back from the linear index 6
:
>>> np.unravel_index(6, (3, 4))
(1, 2)
Note: The above glosses over a few details. 1) Translating the item index to memory address also has to account for item size. For example, an integer typically has 4 or 8 bytes. So, in the latter case, the memory address for item i
would be base + 8 x i
. 2). NumPy is a bit more flexible than suggested. It can organize ND
data column-by-column if desired. It can even handle data that are not contiguous in memory but for example leave gaps, etc.
回答2:
We will start with an example in the documentation.
>>> np.unravel_index([22, 41, 37], (7,6))
(array([3, 6, 6]), array([4, 5, 1]))
First, (7,6)
specifies the dimension of target array that we want to turn the indices back into. Second, [22, 41, 37]
are some indices on this array if the array is flattened. If a 7 by 6 array is flattened, its indices will look like
[ 0, 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*]
If we unflatten these indices back to their original positions in a dim (7, 6)
array, it would be
[[ 0, 1, 2, 3, 4, 5],
[ 6, 7, 8, 9, 10, 11],
[12, 13, 14, 15, 16, 17],
[18, 19, 20, 21, *22*, 23], <- (3, 4)
[24, 25, 26, 27, 28, 29],
[30, 31, 32, 33, 34, 35],
[36, *37*, 38, 39, 40, *41*]]
(6, 1) (6,5)
The return values of the unravel_index
function tell you what should have been the indices of [22, 41, 37] if the array is not flattened. These indices should have been [(3, 4), (6, 5), (6,1)]
if the array is not flattened. In other words, the function transfers the indices in a flatten array back to its unflatten version.
https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.unravel_index.html
回答3:
This isn't different in content than the other two answers, but it might be more intuitive. If you have a 2-D matrix, or array, you can reference it in different ways. You could type the (row, col), to get the value at (row, col), or you can give each cell a single-number index. unravel_index just translates between these two ways of referencing values in a matrix.
This is extendable to dimensions larger than 2. You should also be aware of np.ravel_multi_index(), which performs the reverse transformation. Note that it requires the index and the shape of the array.
I also see I have two 10s in the index matrix--whoops.
回答4:
I can explain it with very simple example. This is for np.ravel_multi_index as well as np.unravel_index
X = np.array([[4, 2],
[9, 3],
[8, 5],
[3, 3],
[5, 6]])
X.shape = (5, 2)
Find, where all the value 3 presents in X
idx = np.where(X==3)
Output: idx = (array([1, 3, 3], dtype=int64), array([1, 0, 1], dtype=int64))
i.e, x = [1, 3, 3]
y = [1, 0, 1]
it returns the x, y of indices [because X is 2 dimensional]
If u apply ravel_multi_index for idx obtained
idx_flat = np.ravel_multi_index(idx, X.shape)
Output: idx_flat = array([3, 6, 7], dtype=int64)
idx_flat is a linear index of X where value 3 presents
From the above example, we can understand,
- ravel_multi_index converts multi-dimensional indices(nd array) into single-dimensional indices(linear array)
- It works only on indices i.e. both input and output are indices
The result indices will be direct indices of X.ravel(). You can verify in the below x_linear
x_linear = X.ravel()
Output: x_linear = array([4, 2, 9, 3, 8, 5, 3, 3, 5, 6])
Whereas, unravel_index is very simple, just reverse of above(np.ravel_multi_index)
idx = np.unravel_index(idx_flat , X.shape)
Output: (array([1, 3, 3], dtype=int64), array([1, 0, 1], dtype=int64))
which is same as idx = np.where(X==3)
- unravel_index converts single-dimensional indices(linear array) into multi-dimensional indices(nd array)
- It works only on indices i.e. both input and output are indices