任意维数的Numpy子阵列

任意维数的Numpy子阵列,numpy,multidimensional-array,slice,matrix-indexing,Numpy,Multidimensional Array,Slice,Matrix Indexing,在Numpy中,假设您有一个Nd数组a,您可以通过执行a[…,0]对最后一个维度进行切片,也可以通过执行a[0]对第一个维度进行切片。我想把这个操作推广到所有维度(不只是第一个维度或最后一个维度),我想把它推广到任意N的Nd数组,这样,如果A3是一个3d数组,A4是一个4d数组,func(A3,dim=1,slice=0)给我A3[:,0,:]和func(A4,dim=1,slice=0)给我A4[:,0,:,:,:] 我已经寻找了一段时间,终于找到了如何在不进行可怕的黑客攻击的情况下做到这一点

在Numpy中,假设您有一个Nd数组a,您可以通过执行
a[…,0]
对最后一个维度进行切片,也可以通过执行
a[0]
对第一个维度进行切片。我想把这个操作推广到所有维度(不只是第一个维度或最后一个维度),我想把它推广到任意N的Nd数组,这样,如果A3是一个3d数组,A4是一个4d数组,
func(A3,dim=1,slice=0)
给我
A3[:,0,:]
func(A4,dim=1,slice=0)
给我
A4[:,0,:,:,:]

我已经寻找了一段时间,终于找到了如何在不进行可怕的黑客攻击的情况下做到这一点(比如交换维度,直到感兴趣的维度排在最后一位)。所以我在这里发布的代码满足我的需要,但是

1) 我一直在寻求改善自己的建议

2) 正如我所说,我已经寻找了一段时间,但从来没有找到任何可以对其他人有用的东西

def fancy_subarray(farray, fdim, fslice):
    # Return the farray slice at position fslice in dimension fdim

    ndim = farray.ndim

    # Handle negative dimension and slice indexing
    if fdim < 0:
        fdim += ndim
    if fslice < 0:
        fslice += v.shape[fdim]

    # Initilize slicing tuple
    obj = ()

    for i in range(ndim):
        if i == fdim:
            # Only element fslice in that dimension
            obj += (slice(fslice, fslice+1, 1),)
        else:
            # "Full" dimension
            obj += (slice(None,None,1),)

    return farray[obj].copy()
def fancy_子阵列(远场、fdim、fslice):
#在尺寸fdim中的fslice位置返回远射线切片
ndim=farray.ndim
#处理负维度和切片索引
如果fdim<0:
fdim+=ndim
如果fslice<0:
fslice+=v.shape[fdim]
#初始化切片元组
obj=()
对于范围内的i(ndim):
如果i==fdim:
#该维度中只有元素fslice
obj+=(切片(fslice,fslice+1,1),)
其他:
#“完整”维度
obj+=(切片(无,无,1),)
返回farray[obj].copy()
因此,这个小函数只是通过将
slice(None,None,1)
连接到我们不想切片的维度的位置,并将
slice(fslice,fslice+1,1)
连接到感兴趣的维度中来构建切片元组。然后返回子数组。它处理负索引

这和直接索引有一点不同:如果A3是3x4x5,
A3[:,0,:]
将是3x5,而
fancy_子数组(A3,fdim=1,fslice=0)
将是3x1x5。此外,该函数“自然”处理越界维度和索引。如果
fdim>=farray.ndim
函数只返回完整数组,因为for循环中的If条件永远不会为True,如果
fslice>=farray.shape[fdim]
返回的子数组在维度fdim中的大小为0

当然,这可以很容易地扩展到不仅仅是在一个维度中选择一个元素


谢谢

我认为您的操作过于复杂,尤其是在处理
fslice
时。如果你这么做了:

def fancy_subarray(farray, fdim, fslice):
    fdim += farray.ndim if fdim < 0 else 0
    index = ((slice(None),) * fdim + (fslice,) +
             (slice(None),) * (farray.ndim - fdim - 1))
    return farray[index]

我认为您的操作过于复杂,尤其是在处理
fslice
时。如果你这么做了:

def fancy_subarray(farray, fdim, fslice):
    fdim += farray.ndim if fdim < 0 else 0
    index = ((slice(None),) * fdim + (fslice,) +
             (slice(None),) * (farray.ndim - fdim - 1))
    return farray[index]

伟大的比我的for循环更好地构造索引。我还看到您删除了.copy(),切片不是通常只返回阵列上的视图吗?太好了!比我的for循环更好地构造索引。我还看到您删除了.copy(),切片不是通常只返回数组上的视图吗?