如何将一个numpy数组Map到另一个numpy数组

x4shl7ld  于 2023-10-19  发布在  其他
关注(0)|答案(3)|浏览(128)

我有两个numpy数组。3D或2D阵列reference和3D阵列map_
在本例中,设Reference为

  1. reference = array([[ [11,12,13], [14,15,16], [17,18,19] ],
  2. [ [21,22,23], [24,25,26], [27,28,29] ],
  3. [ [31,32,33], [34,35,36], [37,38,39] ],
  4. [ [41,42,43], [44,45,46], [47,48,49] ]])

让Map成为

  1. map_ = array([[ [0,0], [1,2], [2,2] ],
  2. [ [2,1], [3,2], [3,0] ]])

结果应该是

  1. array([[ [11,12,13], [27,28,29], [37,38,39] ],
  2. [ [24,25,36], [47,48,49], [41,42,43] ]])

我可以把它解为:

  1. array([[reference[i[0],i[1],:] for i in j] for j in map_])

然而,当map_和reference是千乘千的数组时,这会变得非常慢。
有没有最快的方法来实现这一点?

xzlaal3s

xzlaal3s1#

使用高级索引:

  1. result = reference[map[:,:,0], map[:,:,1]]

(BTW避免使用关键字map作为变量名...)
时间:

  1. import timeit
  2. %timeit test = np.array([[reference[i[0],i[1],:] for i in j] for j in mp])
  3. # 4.53 µs ± 72.5 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)
  4. %timeit test = reference[mp[:,:,0], mp[:,:,1]]
  5. # 1.64 µs ± 4.13 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)

在更大的阵列上,增益可能会更大...例如,对于map = np.random.randint(0,3,size=(100,100,2)),我们得到

  1. 4.11 ms ± 15.6 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

V.S.

  1. 98.5 µs ± 200 ns per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
展开查看全部
cgyqldqp

cgyqldqp2#

类似于@Julien的答案,但使用元组索引。你只需要把map_的尺寸按正确的顺序排列:

  1. reference[tuple(np.moveaxis(map_, 2, 0))]

输出量:

  1. array([[[11, 12, 13],
  2. [27, 28, 29],
  3. [37, 38, 39]],
  4. [[34, 35, 36],
  5. [47, 48, 49],
  6. [41, 42, 43]]])

也就是说,如果map_是:

  1. array([[[0, 1, 2],
  2. [2, 3, 3]],
  3. [[0, 2, 2],
  4. [1, 2, 0]]])
展开查看全部
v64noz0r

v64noz0r3#

编辑:朱利安的回答更简洁,应该被接受这个问题。我花了一些时间写这个答案,所以我把它作为1留在这里。我花了很多时间来写,2。其他人可能会在这里面找到一些东西(谁知道呢)
简短的形式在这里。找到下面的长形式:

  1. reference = array([[ [11,12,13], [14,15,16], [17,18,19] ],
  2. [ [21,22,23], [24,25,26], [27,28,29] ],
  3. [ [31,32,33], [34,35,36], [37,38,39] ],
  4. [ [41,42,43], [44,45,46], [47,48,49] ]])
  5. idx = array([
  6. [[0, 0], [1, 2], [2, 2]],
  7. [[2, 1], [3, 2], [3, 0]]
  8. ])
  9. xd, yd = idx.shape[0], idx.shape[1]
  10. zd = reference.shape[2]
  11. idx = idx.reshape((xd * yd, 2))
  12. indexed_reference = reference[idx[:,0], idx[:, 1]].reshape((xd, yd, zd))
  13. print(indexed_reference)

首先,将你的Map重塑为一个2d数组,以便于索引。注意,我将使用idx而不是map,因为map是python中预定义的函数:

  1. idx = array([
  2. [[0, 0], [1, 2], [2, 2]],
  3. [[2, 1], [3, 2], [3, 0]]
  4. ])
  5. # idx.shape -> (2, 3, 2), make this (6,2). not reshaped dimensions' product must be constant. 2x3x3 == 6x2
  6. # you can probably also (multiply the first two, last) if you want to make it generic
  7. reshaped_idx = idx.reshape((6,2))
  8. # reshaped_idx = array([[0, 0], [1, 2], [2, 2], [2, 1], [3, 2], [3, 0]])
  9. # now just use the indexes to map the original array
  10. reference = array([[ [11,12,13], [14,15,16], [17,18,19] ],
  11. [ [21,22,23], [24,25,26], [27,28,29] ],
  12. [ [31,32,33], [34,35,36], [37,38,39] ],
  13. [ [41,42,43], [44,45,46], [47,48,49] ]])
  14. indexed_reference = reference[reshaped_idx[:,0], reshaped_idx[:,1]]
  15. # array([
  16. # [11, 12, 13], [27, 28, 29], [37, 38, 39],
  17. # [34, 35, 36], [47, 48, 49], [41, 42, 43]
  18. # ])
  19. # indexed_reference.shape -> (6,3) -> 6x3 = 18
  20. # reshape this to the original idx
  21. indexed_reference_reshaped = indexed_reference.reshape((2,3,3))
  22. # answer: array([
  23. # [[11, 12, 13],[27, 28, 29], [37, 38, 39]],
  24. # [[34, 35, 36],[47, 48, 49], [41, 42, 43]]
  25. # ])
展开查看全部

相关问题