如何重新索引3d numpy数组

时间:2018-06-17 13:09:35

标签: python arrays numpy indexing

假设我们有一个3D数组:

new_array = np.zeros((2, 2, 2)) x,y,z = np.meshgrid(array, array, array)

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

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]]] 这个吗?

修改

是的,有......非常简单:

Banana

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

1 个答案:

答案 0 :(得分: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]])