从 numpy 数组创建一组切片,用于并行化

Create a set of slices from a numpy array, for parallelization

我有一个类似 ids = ([0,0,0,1,1,2,2,2,2,4,5,5,5]) 的 numpy 数组和一些其他长度相同的 numpy 数组(比如 ab)。我想使用这些数组的切片执行一些独立的操作,这些切片定义为共享相同(连续)一组 id 的索引。 IE。我想定义一组像

这样的切片
slice_0 = 0:3
slice_1 = 3:5
slice_2 = 5:9
...

这样我就可以为每个 n 并行调用一个函数 f(a[slice_n],b[slice_n])。如何在 numpy 中构造切片?如果有帮助,在 R 中我会用 tapply.

之类的东西来做

我不确定我理解你的问题,也许你是故意的

slice_0 = 0:3
slice_1 = 3:5
slice_2 = 5:9
slice_3 = 9:10
slice_4 = 10:13

如果是这种情况,可以使用NumPy的unique:

_, idx, count = numpy.unique(ids, return_index=True, return_counts=True)

切片的下限为idx,上限为idx + count

一种方法:

In [12]: arrays=vstack((a,b))  

In [13]: arrays
Out[13]: 
array([[4, 1, 4, 2, 5, 7, 1, 5, 9],
       [8, 1, 1, 1, 9, 3, 0, 3, 1]])

In [14]: subarrays=np.split(arrays,[3,5],axis=1)

In [15]: subarrays
Out[15]: 
[array([[4, 1, 4],
        [8, 1, 1]]), 
 array([[2, 5],
        [1, 9]]), 
 array([[7, 1, 5, 9],
        [3, 0, 3, 1]])]

In [16]: [multiply(a,b) for (a,b) in subarrays]
Out[16]: [array([32,  1,  4]), array([ 2, 45]), array([21,  0, 15,  9])]

如果你想沿着一个轴将数组分割成块,最简单的方法是 np.split:

>>> a = np.arange(10)
>>> split_points = (2,5,7)
>>> np.split(a, split_points)
[array([0, 1]), array([2, 3, 4]), array([5, 6]), array([7, 8, 9])]

如果你想要均匀分割,你可以使用 np.arange 代替 split_points

要从 id 数组创建分割点,请使用 split_points = np.where(np.diff(ids))[0] + 1

如果您的 ID 数组已排序并且您的 ID 没有重复,那么 split_points = np.searchsorted(ids, ids_wor)[1:] 可能会更快。

获得你的分裂点:

spl=np.r_[0, np.where(np.nonzero(np.diff(ids)))[0] + 1, ids.size]

然后是切片列表

slices=[slice(i,j) for i,j in zip(spl[:-1].flat, spl[1:].flat)]

或拆分您的其他阵列

a_spl=np.split(a,spl[1:-1])

编辑:由于 idx 已排序并按顺序排列,您可以执行上面的 unique 或执行布尔切片(如果您有记忆)

slices = list(np.unique(ids)[:,None] == ids[None,:])