用2D数组numpy索引3D数组

时间:2019-03-07 23:45:00

标签: python arrays numpy

我正在尝试操纵索引和源数组,使得:

结果[i] [j] [k] =源[i] [索引[i] [j] [k]]

我知道如何使用for循环来做到这一点,但是我使用的是巨型数组,我想使用更省时的方法。我尝试使用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]]]

1 个答案:

答案 0 :(得分:0)

使用整数高级索引的解决方案:

给出:

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]]]

说明:

要使用Integer Advanced Indexing,关键规则是:

  1. 我们必须提供由整数索引组成的索引数组。
  2. 我们必须提供与源数组中的维度一样多的这些索引数组。
  3. 这些索引数组的形状必须相同,或者至少所有它们都可以广播为单个最终形状。

整数高级索引的工作原理是:

鉴于源数组的尺寸为n,因此我们提供了n整数索引数组:

  1. 所有这些索引数组,如果不是相同的统一形状,将被广播为单一的统一形状。
  2. 要访问源数组中的任何元素,显然我们需要一个n元组的索引。因此,要从源数组生成结果数组,我们需要几个n元组,最终结果数组的每个元素位置都需要一个n元组。对于结果数组的每个元素位置,将从广播的索引数组中的相应元素位置构造索引的n个元组。 (如上所述,请记住结果数组的形状与广播索引数组的形状完全相同)。
  3. 因此,通过串联遍历索引数组,我们获得了生成结果数组所需的所有n元组,其形状与广播的索引数组相同。

将此说明应用于上面的示例:

  1. 我们的源数组为nd_source = np.array(source),即2d。
  2. 我们的最终结果形状为(3,2,4)

  3. 因此,我们需要提供2索引数组,并且这些索引数组必须为(3,2,4)的最终结果形状,或者可以广播为(3,2,4)形状。 / p>

  4. 我们的第一个索引数组是row_indices = np.arange(source_rows).reshape(-1,1,1)。 (source_rows是源中的行数,在此示例中为3。此索引数组的形状为(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]]]

  5. 我们的第二个索引数组是indices。尽管这不是数组,而只是列表的列表,但是当我们将其作为发送索引数组传递时,numpy足够灵活,可以自动将其转换为相应的ndarray。请注意,即使没有任何广播,该数组也已经达到了(3,2,4)的最终期望结果形状。

  6. 依次遍历这两个索引数组(一个广播数组,另一个按原样),numpy生成访问源2d数组{{1}所需的所有2元组。 },并生成形状为nd_source的最终结果。