矢量化Numpy切片操作

cfh*_*cfh 5 python numpy vectorization

说我有一个Numpy矢量,

A = zeros(100)
Run Code Online (Sandbox Code Playgroud)

然后我通过一个断点列表将它分成子向量,这些断点索引到A例如

breaks = linspace(0, 100, 11, dtype=int)
Run Code Online (Sandbox Code Playgroud)

所以i-th子向量将位于索引breaks[i](包括)和breaks[i+1](不包括)之间.休息时间不一定是等间隔的,这只是一个例子.但是,它们将始终严格增加.

现在我想对这些子向量进行操作.例如,如果我想将i-th子向量的所有元素设置为i,我可能会这样做:

for i in range(len(breaks) - 1):
    A[breaks[i] : breaks[i+1]] = i
Run Code Online (Sandbox Code Playgroud)

或者我可能想要计算子向量意味着:

b = empty(len(breaks) - 1)
for i in range(len(breaks) - 1):
    b = A[breaks[i] : breaks[i+1]].mean()
Run Code Online (Sandbox Code Playgroud)

等等.

如何避免使用for循环而是对这些操作进行矢量化?

Div*_*kar 6

你可以用简单的np.cumsum-

import numpy as np

# Form zeros array of same size as input array and 
# place ones at positions where intervals change
A1 = np.zeros_like(A)
A1[breaks[1:-1]] = 1

# Perform cumsum along it to create a staircase like array, as the final output
out = A1.cumsum()
Run Code Online (Sandbox Code Playgroud)

样品运行 -

In [115]: A
Out[115]: array([3, 8, 0, 4, 6, 4, 8, 0, 2, 7, 4, 9, 3, 7, 3, 8, 6, 7, 1, 6])

In [116]: breaks
Out[116]: array([ 0,  4,  9, 11, 18, 20])

In [142]: out
Out[142]: array([0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 4]..)
Run Code Online (Sandbox Code Playgroud)

如果你想要从中获得这些子向量的平均值A,你可以使用np.bincount-

mean_vals = np.bincount(out, weights=A)/np.bincount(out)
Run Code Online (Sandbox Code Playgroud)

如果您希望扩展此功能并使用自定义函数,您可能需要查看MATLAB的accumarray等效内容Python/Numpy:accum源代码可在此处获得.


Jai*_*ime 5

您的问题确实没有一个答案,但您可以使用几种技术作为构建块.另一个你可能会发现有用的:

所有numpy ufunc都有一个.reduceat方法,您可以利用它来进行一些计算:

>>> a = np.arange(100)
>>> breaks = np.linspace(0, 100, 11, dtype=np.intp)
>>> counts = np.diff(breaks)
>>> counts
array([10, 10, 10, 10, 10, 10, 10, 10, 10, 10])
>>> sums = np.add.reduceat(a, breaks[:-1], dtype=np.float)
>>> sums
array([  45.,  145.,  245.,  345.,  445.,  545.,  645.,  745.,  845.,  945.])
>>> sums / counts  # i.e. the mean
array([  4.5,  14.5,  24.5,  34.5,  44.5,  54.5,  64.5,  74.5,  84.5,  94.5])
Run Code Online (Sandbox Code Playgroud)