小编典典

向量化Numpy Slice操作

python

假设我有一个Numpy向量,

A = zeros(100)

然后我将其按索引的断点列表划分为子向量A,例如,

breaks = linspace(0, 100, 11, dtype=int)

因此,i第-个子向量将位于索引breaks[i](包含)和breaks[i+1](排除)之间。中断不一定是等距的,这仅是示例。但是,它们将始终严格增加。

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

for i in range(len(breaks) - 1):
    A[breaks[i] : breaks[i+1]] = i

或者我可能想计算子向量的意思是:

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

等等。

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


阅读 124

收藏
2021-01-20

共1个答案

小编典典

问题的答案确实不是一个单一的答案,而是可以用作构建基块的几种技术。您可能会发现另一个有用的方法:

所有的numpy
ufuncs都有一个.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])
2021-01-20