假设我有一个Numpy向量,
A = zeros(100)
然后我将其按索引的断点列表划分为子向量A,例如,
A
breaks = linspace(0, 100, 11, dtype=int)
因此,i第-个子向量将位于索引breaks[i](包含)和breaks[i+1](排除)之间。中断不一定是等距的,这仅是示例。但是,它们将始终严格增加。
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循环,而是对这些操作进行向量化?
for
问题的答案确实不是一个单一的答案,而是可以用作构建基块的几种技术。您可能会发现另一个有用的方法:
所有的numpy ufuncs都有一个.reduceat方法,您可以利用它来进行一些计算:
.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])