我正在尝试操纵索引和源数组,以便:
结果[i] [j] [k] = source [i] [indices [i] [j] [k]]
我知道如何使用循环进行此操作,但是我正在使用巨大的阵列,我想使用更多的时间效率。我尝试使用Numpy的高级索引,但我真的不理解。
示例功能:
source = [[0.0 0.1 0.2 0.3]
[1.0 1.1 1.2 1.3]
[2.0 2.1 2.2 2.3]]
indices = [[[3 1 0 1]
[3 0 0 3]]
[[0 1 0 2]
[3 2 1 1]]
[[1 1 0 1]
[0 1 2 2]]]
# result[i][j][k] = source[i][indices[i][j][k]]
result = [[[0.3 0.1 0.0 0.1]
[0.3 0.0 0.0 0.3]]
[[1.0 1.1 1.0 1.2]
[1.3 1.2 1.1 1.1]]
[[2.1 2.1 2.0 2.1]
[2.0 2.1 2.2 2.2]]]
使用整数高级索引:
给定:
source = [[0.0, 0.1, 0.2, 0.3],
[1.0, 1.1, 1.2, 1.3],
[2.0, 2.1, 2.2, 2.3]]
indices = [[[3, 1, 0, 1],
[3, 0, 0, 3]],
[[0, 1, 0, 2],
[3, 2, 1, 1]],
[[1, 1, 0, 1],
[0, 1, 2, 2]]]
使用以下方式:
import numpy as np
nd_source = np.array(source)
source_rows = len(source) # == 3, in above example
source_cols = len(source[0]) # == 4, in above example
row_indices = np.arange(source_rows).reshape(-1,1,1)
result = nd_source [row_indices, indices]
结果:
print (result)
[[[0.3 0.1 0. 0.1]
[0.3 0. 0. 0.3]]
[[1. 1.1 1. 1.2]
[1.3 1.2 1.1 1.1]]
[[2.1 2.1 2. 2.1]
[2. 2.1 2.2 2.2]]]
说明:
要使用整数高级索引,关键规则是:
- 我们必须提供由整数索引组成的索引阵列。
- 我们必须提供许多这些索引数组,因为源数组中有尺寸。
- 这些索引阵列的形状必须相同,或者,至少所有这些索引阵列都必须在单个最终形状上播放。
整数高级索引的工作方式是:
鉴于源数组具有n
维度,因此我们提供了n
整数索引数组:
- 所有这些索引阵列(如果不是相同的均匀形状)将被广播为单一均匀形状。
- 要访问源数组中的任何元素,我们显然需要一个索引。因此,为了从源数组生成结果数组,我们需要几个n个tuples,对于最终结果阵列的每个元素位置一个n核。对于结果数组的每个元素位置,索引的n核心将由广播索引阵列中的相应元素位置构造。(请记住,结果数组的形状与已广播的索引阵列完全相同,如上所述)。
- 因此,通过串联中的索引阵列,我们获得了生成结果数组所需的所有n-tuples,其形状与广播的索引阵列相同。
将此说明应用于上述示例:
- 我们的源数组是
nd_source = np.array(source)
,是2d。 我们的最终结果形状是
(3,2,4)
。因此,我们需要提供
2
索引数组,这些索引数组必须处于(3,2,4)
的最终结果形状,或可广播到(3,2,4)
Shape。我们的第一个索引数组是
row_indices = np.arange(source_rows).reshape(-1,1,1)
。(source_rows
是源中的行数,在此示例中为3
)该索引数组具有Shape(3,1,1)
,实际上看起来像[[[0]],[[1]],[[2]]]
。这是可以广播到(3,2,4)
的最终结果形状,并且广播的数组看起来像[[[0,0,0,0],[0,0,0,0]],[[1,1,1,1],[1,1,1,1]],[[2,2,2,2],[2,2,2,2]]]
。我们的第二个索引数组是
indices
。尽管这不是一个数组,而只是列表的列表,但是当我们将其作为发送索引阵列时,Numpy足够灵活,可以自动将其转换为相应的NDARRAY。请注意,即使没有任何广播,此数组也已经处于(3,2,4)
的最终预期结果形状。在串联中遍历这两个索引数组(一个是广播的数组,另一个是一个),numpy生成了访问我们的源2D数组
nd_source
所需的所有2个tuplace,并生成生成形状(3,2,4)
的最终结果。