np.unravel_index
的文档,并尝试使用这个函数,但是我无法弄清楚它在做什么。计算机内存是线性寻址的。每个内存单元对应一个数字。可以通过基地址和索引来寻址一块内存。例如,假设基地址为10,000:
item index 0 1 2 3
memory address 10,000 10,001 10,002 10,003
为了存储多维块,必须将它们的几何形状以某种方式放在线性内存中。在C
和NumPy
中,这是逐行完成的。一个2D示例如下:
| 0 1 2 3
--+------------------------
0 | 0 1 2 3
1 | 4 5 6 7
2 | 8 9 10 11
例如,在这个3x4的块中,二维索引(1, 2)
对应于线性索引6
,即1 x 4 + 2
。
unravel_index
函数执行的是相反的操作。给定一个线性索引和块的维度,它会计算出对应的ND
索引。因此,在我们的示例中,我们可以通过线性索引6
获得原始的二维索引(1, 2)
:
>>> np.unravel_index(6, (3, 4))
(1, 2)
注意:上述内容略去了一些细节。1)将项索引转换为内存地址还必须考虑项大小。例如,整数通常有4或8个字节。因此,在后一种情况下,项目i的内存地址将为base + 8 x i
。2)NumPy比建议的更加灵活。如果需要,它可以按列组织ND
数据。它甚至可以处理在内存中不连续但留有间隔等的数据等问题。np.unravel_index(i, (n, n)) == (i//n, i%n)
- Andy我们将从文档中的一个示例开始。
>>> np.unravel_index([22, 41, 37], (7,6))
(array([3, 6, 6]), array([4, 5, 1]))
首先,(7,6)
指定了我们想要将索引转换回来的目标数组的维度。其次,[22, 41, 37]
是该数组在被展平后的一些索引。如果一个大小为7乘6的数组被展平,它的索引看起来会像是:
[ 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*]
如果我们将这些索引展开,回到它们在 (7, 6)
数组中的原始位置,那么它将是:
如果我们将这些索引展开,回到它们在 (7, 6)
数组中的原始位置,那么它将是:
[[ 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)
unravel_index
函数的返回值告诉您,如果数组未被展平,[22, 41, 37]应该是什么索引。 如果数组未被展平,这些索引应该是[(3, 4), (6, 5), (6,1)]
。 换句话说,该函数将展平数组中的索引转换回其未展平版本。
https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.unravel_index.html
>>> X = np.array([[4, 2],
[9, 3],
[8, 5],
[3, 3],
[5, 6]])
>>> X.shape
(5, 2)
>>> idx = np.where(X==3)
>>> idx
(array([1, 3, 3], dtype=int64), array([1, 0, 1], dtype=int64))
例如:x = [1,3,3]
,y = [1,0,1]
,它会返回索引的 x 和 y 值(因为 X 是二维的)。
如果您对获得的 idx
应用ravel_multi_index:
>>> idx_flat = np.ravel_multi_index(idx, X.shape)
>>> idx_flat
array([3, 6, 7], dtype=int64)
idx_flat
是X中数值为3的元素的线性索引。
从上面的示例中,我们可以理解:
ravel_multi_index
将多维索引(nd数组)转换为单维索引(线性数组)结果索引将是X.ravel()
的直接索引。您可以在下面的x_linear
中进行验证:
>>> x_linear = X.ravel()
>>> x_linear
array([4, 2, 9, 3, 8, 5, 3, 3, 5, 6])
相比之下,unravel_index 非常简单,只是上面函数(np.ravel_multi_index)的反转。
>>> idx = np.unravel_index(idx_flat , X.shape)
>>> idx
(array([1, 3, 3], dtype=int64), array([1, 0, 1], dtype=int64))
这与idx = np.where(X==3)
相同。
unravel_index
将单维度索引(线性数组)转换为多维度索引(nd数组)给定一个指向.ravel()
ed数组的raveled_index
,np.unravel_index
会计算出等效于基础数组的展平索引:
import numpy as np
my_array = np.random.random((100, 42))
raveled_array = my_array.ravel()
raveled_index = 1337
unraveled_index = np.unravel_index(raveled_index, my_array.shape)
assert raveled_array[raveled_index] == my_array[unraveled_index]
两个需要了解的知识点:
raveled_array
也被称为flat_array
;因此,raveled_index
或flat_index
仅是指向“压平”数组的索引。此外,由于压平数组已经“丢失”了其原始形状信息,因此在调用np.unravel_index
时需要添加这些信息。
unraveled_index
通常被称为multi_index
。这是因为你需要多个值(一个N元组)来索引任何具有my_array.dim == N
的数组中的元素。因此,np.unravel_index
的反函数被称为np.ravel_multi_index
。
这仅适用于2D情况,但在此情况下,np.unravel_index函数返回的两个坐标相当于执行floor除法并分别应用模函数。
for j in range(1,1000):
for i in range(j):
assert(np.unravel_index(i,(987654321,j))==(i//j,i%j))
形状数组的第一个元素(即987654321)除了限制可以通过函数传递的展开线性索引的最大值之外,没有其他意义。
np.ravel_multi_index
中,这里有一些解释
可以反过来理解。 - Divakar