【问题标题】:Extract elements of a 2d array with indices from another 2d array从另一个二维数组中提取具有索引的二维数组的元素
【发布时间】:2014-08-13 12:16:00
【问题描述】:

我有一个 2d numpy 数组:data.shape==(n,8) 和另一个 ind.shape=(n,4)。 ind 数组与 data 长度相同,并且包含像 [4,3,0,6] 这样的索引。如何创建另一个 shape==(n,4) 的数组,其中包含由 ind 的索引指定的数据中的元素?我的实际数组很长(形状[0]),所以循环很慢。一定有比循环更好的方法吗?

import numpy as np
# Example data
data = np.array([[ 0.44180102, -0.05941365,  2.1482739 , -0.56875081, -1.45400572,
        -1.44391254, -0.33710766, -0.44214518],
       [ 0.79506417, -2.46156966, -0.09929341, -1.07347179,  1.03986533,
        -0.45745476,  0.58853107, -1.08565425],
       [ 1.40348682, -1.43396403,  0.8267174 , -1.54812358, -1.05854445,
         0.15789466, -0.0666025 ,  0.29058816]])
ind = np.array([[3, 4, 1, 5],
                [4, 7, 0, 1],
                [5, 1, 3, 6]])

# This is the part I want to vectorize:
out = np.zeros(ind.shape)
for i in range(ind.shape[0]):
    out[i,:] = data[i,ind[i,:]]

# This should be good
assert np.all(out == np.array([[-0.56875081, -1.45400572, -0.05941365, -1.44391254],
                        [ 1.03986533, -1.08565425,  0.79506417, -2.46156966],
                        [ 0.15789466, -1.43396403, -1.54812358, -0.0666025 ]]))

【问题讨论】:

    标签: python arrays numpy


    【解决方案1】:

    如果我们索引到 raveled data 数组,这很容易做到:

    out = data.ravel()[ind.ravel() + np.repeat(range(0, 8*ind.shape[0], 8), ind.shape[1])].reshape(ind.shape)
    

    说明

    如果分成三个步骤可能更容易理解:

    indices = ind.ravel() + np.repeat(range(0, 8*ind.shape[0], 8), ind.shape[1])
    out = data.ravel()[indices]
    out = out.reshape(ind.shape)
    

    ind 包含我们想要的来自data 的元素的信息。不幸的是,它以二维指数表示。上面的第一行将这些转换为一维解压的dataindices。上面的第二行从 raveled 数组data 中选择这些元素。第三行将二维形状恢复为outind 表示的二维索引转换为 indindices 具有索引

    【讨论】:

      【解决方案2】:

      你想要的是这样的:

      import numpy as np
      data = np.array([[ 0.4, -0.1,  2.1, -0.6, -1.5, -1.4, -0.3, -0.4],
                       [ 0.8, -2.5, -0.1, -1.1,  1. , -0.5,  0.6, -1.1],
                       [ 1.4, -1.4,  0.8, -1.5, -1.1,  0.2, -0.1,  0.3]])
      expected = np.array([[-0.6, -1.5, -0.1, -1.4],
                           [ 1. , -1.1,  0.8, -2.5],
                           [ 0.2, -1.4, -1.5, -0.1]])
      
      indI = np.array([[0, 0, 0, 0],
                       [1, 1, 1, 1],
                       [2, 2, 2, 2]])
      indJ = np.array([[3, 4, 1, 5],
                       [4, 7, 0, 1],
                       [5, 1, 3, 6]])
      out = data[indI, indJ]
      assert np.all(out == expected)
      

      注意indIindJ 的形状相同,而且

      out[i, j] == data[indI[i, j], indJ[i, j]]
      

      对于所有ij

      您可能已经注意到indI 非常重复。由于 numpy 的 broadcasting 魔法,您可以简单地将 indI 发送到:

      indI = np.array([[0],
                       [1],
                       [2]])
      

      您可以通过几种不同的方式构建这种indI 数组,这是我最喜欢的:

      a, b = indJ.shape
      indI, _ = np.ogrid[:a, :0]
      out = data[indI, indJ]
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-06-04
        • 2012-04-10
        • 2017-05-22
        • 1970-01-01
        • 2021-11-26
        • 2020-03-09
        • 2016-08-26
        • 2021-03-03
        相关资源
        最近更新 更多