小能豆

一次访问 numpy 数组中的块

py

提供了一个 numpy 数组:

arr = np.array([0,1,2,3,4,5,6,7,8,9,10,11,12])

我想知道如何访问选定大小的和选定的分隔符,包括连接和切片:

例如:获取由两个值分隔的大小为 3 的块:

arr_chunk_3_sep_2 = np.array([0,1,2,5,6,7,10,11,12])
arr_chunk_3_sep_2_in_slices = np.array([[0,1,2],[5,6,7],[10,11,12])

最有效的方法是什么?如果可能的话,我想尽可能避免复制或创建新对象。也许Memoryviews可以帮到你?


阅读 14

收藏
2024-12-09

共1个答案

小能豆

方法 #1

以下是其中的一个masking

def slice_grps(a, chunk, sep):
    N = chunk + sep
    return a[np.arange(len(a))%N < chunk]

样本运行 -

In [223]: arr
Out[223]: array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12])

In [224]: slice_grps(arr, chunk=3, sep=2)
Out[224]: array([ 0,  1,  2,  5,  6,  7, 10, 11, 12])

方法 #2

如果输入数组的最后一块有足够的跑道,我们可以,我们可以利用np.lib.stride_tricks.as_strided,受启发从每个元素块中this post选择元素-m``n

# https://stackoverflow.com/a/51640641/ @Divakar
def skipped_view(a, m, n):
    s = a.strides[0]
    strided = np.lib.stride_tricks.as_strided
    shp = ((a.size+n-1)//n,n)
    return strided(a,shape=shp,strides=(n*s,s), writeable=False)[:,:m]

out = skipped_view(arr,chunk,chunk+sep)

请注意,输出将是输入数组的视图,因此没有额外的内存开销并且实际上是免费的!

样本运行使事情变得清晰 -

In [255]: arr
Out[255]: array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12])

In [256]: chunk = 3

In [257]: sep = 2

In [258]: skipped_view(arr,chunk,chunk+sep)
Out[258]: 
array([[ 0,  1,  2],
       [ 5,  6,  7],
       [10, 11, 12]])

# Let's prove that the output is a view indeed
In [259]: np.shares_memory(arr, skipped_view(arr,chunk,chunk+sep))
Out[259]: True
2024-12-09