【问题标题】:How to re-index 3d numpy array如何重新索引 3d numpy 数组
【发布时间】:2018-06-17 13:09:35
【问题描述】:

假设我们有一个像这样的 3D 数组:

array = np.arange(8).reshape(2,2, 2) new_array = np.zeros((2, 2, 2))

假设我们的数组有一些新的随机 x,y,z 索引

x,y,z = np.meshgrid(array, array, array)

重新索引我们的数组的最快方法是什么?

这里给出一个简单的解决方案:

for x in range(0, 3):
    for y in range(0, 3):
        for z in range(0, 3):
            new_x = x_coord[x,y,z]
            new_y = y_coord[x,y,z]
            new_z = z_coord[x,y,z]

            new_array[x,y,z] = array[new_x, new_y, new_z]

有没有我不知道的one-liner

编辑

是的,有……非常简单:

vol = np.arange(8).reshape(2,2, 2)
arr = np.arange(2)
x,y,z = np.meshgrid(arr, arr, arr)


print(vol)
print(vol[y, x, z]) ### ---> You have to swap the axes here tho. Does anyone know why?

[[[0 1]
  [2 3]]

 [[4 5]
  [6 7]]]
[[[0 1]
  [2 3]]

 [[4 5]
  [6 7]]]

而且,它非常慢。任何想法如何提高性能?

【问题讨论】:

  • 如果您的示例使用整数进行索引并且工作正常,会好很多。
  • 已为您修复!现在好点了?还是你要我举个恰当的例子?我认为这个想法应该很简单?我不知道为什么 numpy 中没有简单的操作来做到这一点,因为我认为这只是一个简单的重新索引任务。 @miradulo
  • 你能用文字解释一下你想象的算法在做什么吗?
  • randint 将简化随机值的生成。
  • 你试过arr[xcord, ycord,zcord]吗?

标签: python arrays numpy indexing


【解决方案1】:

设置:

In [54]: arr = np.arange(9).reshape(3,3)
In [55]: x = np.random.randint(0,3,(3,3))
In [56]: y = np.random.randint(0,3,(3,3))
In [57]: x
Out[57]: 
array([[2, 0, 1],
       [0, 2, 1],
       [0, 0, 1]])
In [58]: y
Out[58]: 
array([[0, 0, 0],
       [0, 1, 1],
       [0, 1, 0]])

这些索引数组最简单的应用:

In [59]: arr[x,y]
Out[59]: 
array([[6, 0, 3],
       [0, 7, 4],
       [0, 1, 3]])

迭代等价物:

In [60]: out = np.empty_like(arr)
In [61]: for i in range(3):
    ...:     for j in range(3):
    ...:         out[i,j] = arr[x[i,j], y[i,j]]
    ...:         
In [62]: out
Out[62]: 
array([[6, 0, 3],
       [0, 7, 4],
       [0, 1, 3]])

您的代码不一样,因为它在迭代时修改了源数组:

In [63]: arr1 = arr.copy()
In [64]: for i in range(3):
    ...:     for j in range(3):
    ...:         arr1[i,j] = arr1[x[i,j], y[i,j]]
    ...:         
In [65]: arr1
Out[65]: 
array([[6, 6, 3],
       [6, 7, 7],
       [6, 6, 6]])

没有简单的等价物。


您可以使用arr[x_coord,y_coord,z_coord] 进行索引,只要一个索引数组一起广播。它们都具有相同的形状,这是微不足道的。

In [68]: x1 = np.random.randint(0,3,(2,4))
In [69]: x1
Out[69]: 
array([[2, 0, 2, 0],
       [0, 0, 0, 2]])
In [70]: arr[x1,x1]
Out[70]: 
array([[8, 0, 8, 0],
       [0, 0, 0, 8]])

从数组中选择随机值的更简单方法是创建随机行和列选择器,并使用ix_ 创建一起广播的数组:

In [71]: x1 = np.random.randint(0,3,(3))
In [72]: y1 = np.random.randint(0,3,(3))

In [75]: np.ix_(x1,y1)
Out[75]: 
(array([[2],
        [1],
        [1]]), array([[2, 2, 1]]))
In [76]: arr[np.ix_(x1,y1)]
Out[76]: 
array([[8, 8, 7],
       [5, 5, 4],
       [5, 5, 4]])

听起来你只是想打乱数组的值,比如:

In [95]: arr
Out[95]: 
array([[0, 1, 2],
       [3, 4, 5],
       [6, 7, 8]])
In [96]: np.random.shuffle(arr.ravel())
In [97]: arr
Out[97]: 
array([[0, 1, 2],
       [7, 4, 3],
       [6, 5, 8]])

【讨论】:

  • 我刚刚创建了一个随机数组,以使我的“问题”的输入更简单。但最终将只有一个索引最终会出现另一个索引。所以基本上是基于新转换索引的值排列。
  • 无论如何,如果 3 个坐标数组具有正确的值和形状,它们可以像我最初指出的那样使用 arr[x, y, z]
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多