在 NumPy 数组中推广切片操作
这个问题基于这个较旧的问题:
This question is based on this older question:
给定一个数组:
In [122]: arr = np.array([[1, 3, 7], [4, 9, 8]]); arr
Out[122]:
array([[1, 3, 7],
[4, 9, 8]])
并给出它的索引:
In [127]: np.indices(arr.shape)
Out[127]:
array([[[0, 0, 0],
[1, 1, 1]],
[[0, 1, 2],
[0, 1, 2]]])
我如何才能将它们整齐地堆叠在一起形成一个新的二维数组?这就是我想要的:
How would I be able to stack them neatly one against the other to form a new 2D array? This is what I'd like:
array([[0, 0, 1],
[0, 1, 3],
[0, 2, 7],
[1, 0, 4],
[1, 1, 9],
[1, 2, 8]])
Divakar 的这个解决方案是我目前用于二维数组的解决方案:
This solution by Divakar is what I currently use for 2D arrays:
def indices_merged_arr(arr):
m,n = arr.shape
I,J = np.ogrid[:m,:n]
out = np.empty((m,n,3), dtype=arr.dtype)
out[...,0] = I
out[...,1] = J
out[...,2] = arr
out.shape = (-1,3)
return out
现在,如果我想传递一个 3D 数组,我需要修改这个函数:
Now, if I wanted to pass a 3D array, I need to modify this function:
def indices_merged_arr(arr):
m,n,k = arr.shape # here
I,J,K = np.ogrid[:m,:n,:k] # here
out = np.empty((m,n,k,4), dtype=arr.dtype) # here
out[...,0] = I
out[...,1] = J
out[...,2] = K # here
out[...,3] = arr
out.shape = (-1,4) # here
return out
但此函数现在仅适用于 3D 数组 - 我无法将 2D 数组传递给它.
But this function now works for 3D arrays only - I can't pass a 2D array to it.
是否有某种方法可以将其概括为适用于任何维度?这是我的尝试:
Is there some sort of way I can generalise this to work for any dimension? Here's my attempt:
def indices_merged_arr_general(arr):
tup = arr.shape
idx = np.ogrid[????] # not sure what to do here....
out = np.empty(tup + (len(tup) + 1, ), dtype=arr.dtype)
for i, j in enumerate(idx):
out[...,i] = j
out[...,len(tup) - 1] = arr
out.shape = (-1, len(tup)
return out
我遇到了这条线的问题:
I'm having trouble with this line:
idx = np.ogrid[????]
我怎样才能让它工作?
这是处理泛型 ndarrays 的扩展 -
Here's the extension to handle generic ndarrays -
def indices_merged_arr_generic(arr, arr_pos="last"):
n = arr.ndim
grid = np.ogrid[tuple(map(slice, arr.shape))]
out = np.empty(arr.shape + (n+1,), dtype=np.result_type(arr.dtype, int))
if arr_pos=="first":
offset = 1
elif arr_pos=="last":
offset = 0
else:
raise Exception("Invalid arr_pos")
for i in range(n):
out[...,i+offset] = grid[i]
out[...,-1+offset] = arr
out.shape = (-1,n+1)
return out
样品运行
二维案例:
In [252]: arr
Out[252]:
array([[37, 32, 73],
[95, 80, 97]])
In [253]: indices_merged_arr_generic(arr)
Out[253]:
array([[ 0, 0, 37],
[ 0, 1, 32],
[ 0, 2, 73],
[ 1, 0, 95],
[ 1, 1, 80],
[ 1, 2, 97]])
In [254]: indices_merged_arr_generic(arr, arr_pos='first')
Out[254]:
array([[37, 0, 0],
[32, 0, 1],
[73, 0, 2],
[95, 1, 0],
[80, 1, 1],
[97, 1, 2]])
3D 案例:
In [226]: arr
Out[226]:
array([[[35, 45, 33],
[48, 38, 20],
[69, 31, 90]],
[[73, 65, 73],
[27, 51, 45],
[89, 50, 74]]])
In [227]: indices_merged_arr_generic(arr)
Out[227]:
array([[ 0, 0, 0, 35],
[ 0, 0, 1, 45],
[ 0, 0, 2, 33],
[ 0, 1, 0, 48],
[ 0, 1, 1, 38],
[ 0, 1, 2, 20],
[ 0, 2, 0, 69],
[ 0, 2, 1, 31],
[ 0, 2, 2, 90],
[ 1, 0, 0, 73],
[ 1, 0, 1, 65],
[ 1, 0, 2, 73],
[ 1, 1, 0, 27],
[ 1, 1, 1, 51],
[ 1, 1, 2, 45],
[ 1, 2, 0, 89],
[ 1, 2, 1, 50],
[ 1, 2, 2, 74]])