我有一个类似的numpy数组:
array([[ -1. , 184. , 0.5],
[ -1. , 174. , 1.0],
[ -1. , 104. , 0.5],
[ 1. , 44. , 0.5],
[ 1. , 28. , 0.5],
[ 1. , 70. , 0.5],
[ -1. , 34. , 0.5],
...,
[ 1. , 10. , 0.5],
[ 1. , 12. , 0.5],
[ 1. , 86. , 1.0],
[ -1. , 36. , 0.5],
[ 1. , 2. , 0.5],
[ -1. , 32. , 1.5],
[ 1. , 10. , 0.5]])
我有一个函数来查找满足for循环中列出的条件的数组索引:
def loop(array):
n_init = 100
a = np.dot(array[:n_init, 0], array[:n_init, 1])
b = np.sum(array[:n_init, 2])
loc_start = n_init
idx = []
lst_a, lst_b = [], []
lst_a.append(a)
lst_b.append(b)
for step in range(n_init + 1, array.shape[0]):
mean_a = np.mean(lst_a)
mean_b = np.mean(lst_b)
_a = np.dot(array[loc_start:step, 0], array[loc_start:step, 1])
_b = np.sum(array[loc_start:step, 2])
if np.abs(_a) * _b >= np.abs(mean_a) * mean_b:
loc_start = step
lst_a.append(_a)
lst_b.append(_b)
idx.append(step)
return idx
该函数首先初始化n_init行,以计算2个标量a和b,这些标量被附加到稍后在for循环中使用的列表lst_a和lst_b中。
在循环中,从n_init行之后的条目开始,分别显示lst_a和lst_b的平均值,以及_a(从最后一个idx到当前步骤的列0和1的点运算)和_b(从最后一个idx到当前步骤的第2列)。
当_a的绝对值乘以_b的绝对值大于或等于lst_a的均值的绝对值乘以lst_b的均值时,会找到行号,即附加到idx的索引,并作为条件如果满足,则将当前_a和_b分别附加到lst_a和lst_b。当step到达数组的长度时,整个循环结束。
由于该数组具有数百万行,因此需要很长时间才能完成。可以对这个过程进行向量化吗?
答案 0 :(得分:0)
好吧,您正在建立一个状态(lst_a
和lst_b
),并使用它来检查新条目是否应属于该状态。因此,我认为它不能完全矢量化。
您可以尝试加快速度的方法是使用增量计算(实际上是矢量化的逆过程,如果可以的话)。
例如mean_a
和mean_b
当前在每个步骤都被重新计算,即使它没有改变,并且当它改变时,您可以对其进行更新而不是完全重新计算。
还可以更新_a
和_b
而不是重新计算。这样可以节省数组切片和少量计算(如果loc_start
距离不太远,可能不值得)。
试试看并进行比较。
答案 1 :(得分:0)
您无法对其进行矢量化处理(因为您要迭代填充列表并在计算中使用它们),但是您可以预先进行很多矢量化的计算。也许。
def loop(array):
loc_start = 100
A = np.cumsum(array[:, 0] * array[:, 1])
B = np.cumsum(array[:, 2])
a, b = A[loc_start], B[loc_start]
idx = []
lst_a, lst_b = [a], [b]
thr = np.abs(a)/ b
for step in range(n_init + 1, array.shape[0]):
_a = A[step] - a
_b = B[step] - b
if np.abs(_a) * _b >= thr:
loc_start = step
a, b = a_, b_
lst_a.append(a)
lst_b.append(b)
thr = np.abs(np.mean(lst_a)) / np.mean(lst_b)
idx.append(step)
return idx
只要您的cumsum
数组不会溢出(请检查A[-1]
和B[-1]
的值),这应该会更快。