将 ndarray 查看为索引列表和值列表

View ndarray as list of indexes and list of values

我有一个 2 维或 6 维的 ND 数组。 例如:

nd_array = [[90, 80],
            [70, 60], 
            [50, 40]]

我想将其视为索引列表,如下所示:

nd_array_transformed = [[90, 0, 0],
                        [80, 0, 1],
                        [70, 1, 0],
                        [60, 1, 1],
                        [50, 2, 0], 
                        [40, 2, 1]]

或类似的表示。

我找到了二维案例的代码,但我正在寻找更通用的解决方案:

np.array([[nd_array[row][col], row, col] for row in range(nd_array.shape[0]) 
                                         for col in range(nd_array.shape[1])])

是否可以在一般情况下进行此转换,也许使用 *nd_array.shape

您可以使用 itertools.product()range()map() 生成所有可能的索引,然后使用解包运算符将索引添加到每个内部列表。这里使用的示例是二维的,但是使用解包而不是固定数量的 for 循环使得这种方法可以扩展到任意数量的维度:

import numpy as np
from itertools import product
nd_array = np.array([[90, 80],
            [70, 60],
            [50, 40]])

result = np.array([[nd_array[indices], *indices]
    for indices in product(*map(range, nd_array.shape))])
print(result)

用于构造我们在列表理解中迭代的内容的语法有点密集,所以这里有一个更详细的解释:

.shape 生成一个给出数组维度的元组(例如 (3, 2))。给出的例子都会呈现这个形状。

我们希望能够生成由形状给出的所有可能索引(例如 (0, 0), (0, 1) ... (2, 1))。我们将 map()range() 一起使用,获取元组中的每个整数并生成相应的 range() 用该整数初始化(即 (3, 2) 被转换为包含 range(3)range(2))。然后将这个可迭代对象解压缩(使用 *)到 itertools.product()——函数调用本质上变成了 itertools.product(range(3), range(2)),生成一个笛卡尔积,它给了我们所有需要的索引。