如何在numpy中向量化包含if语句的for循环?

时间:2016-12-21 07:00:14

标签: python numpy vectorization

我对numpy很新。我有以下代码,它给了我想要的结果:

import numpy as np

def get_result(S,K,delS):
    res=np.zeros(S.shape[0],dtype=np.float64)
    for j in range(res.shape[0]):
        if S[j]-K>delS:
            res[j]+=np.floor((S[j]-K)/delS)
            K+=np.floor((S[j]-K)/delS)*delS
        elif S[j]-K<-delS:
            res[j]+=np.ceil((S[j]-K)/delS)
            K+=np.ceil((S[j]-K)/delS)*delS
    return res

S=np.array([1.0,1.05,1.1,1.12,1.09,1.14,1.21,1.6,1.05,1.0,0.95,0.90,0.87,0.77,0.63,0.85,0.91,0.76],dtype=np.float64)

K=1.0
delS=0.1

l=get_result(S,K,delS)

for j in range(S.shape[0]):
    print("%d\t%.2f\t%.0f" % (j,S[j],l[j]))

get_result函数包含一个for循环,因此对于较大的输入向量S来说速度很慢。这样的函数可以用numpy语法进行矢量化吗?任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:1)

在数组或计算中处理2个或更多条件时的一般模式是构造一个布尔掩码,并对该掩码为真的元素采取一个动作,并在假的情况下采用不同的行为:

res=np.zeros(S.shape[0],dtype=np.float64)
mask - S-K>delS
res[mask] = ...S[mask]
res[~mask] = ...S[~mask]

变体是使用np.where(mask)来识别索引。

但似乎使您的计算复杂化的是测试不断变化。也就是说,K的{​​{1}}来自j+1的计算。

j

为了处理这种迭代,我们通常会尝试使用for j in range(res.shape[0]): if S[j]-K>delS: res[j]+=np.floor((S[j]-K)/delS) K+=np.floor((S[j]-K)/delS)*delS elif S[j]-K<-delS: res[j]+=np.ceil((S[j]-K)/delS) K+=np.ceil((S[j]-K)/delS)*delS 或其他累积np.cumsum方法。

作为一般规则,当计算可以并行地应用于数组(或数组集)的所有元素时,ufunc代码是最快且最简单的 - 也就是说,不是取决于迭代的顺序。然后我们可以将动作委托给快速编译的numpy函数,如数组加法和乘法。如果计算本质上是串行的(j的值取决于j-1),这就变得更加棘手。

因此,如果我的粗略阅读是正确的,那么if语句就不是困难的,这是循环的串行性质。

=========================

在游戏中,我能够删除numpy(实际上有3个子例子),但它仍然必须是迭代的:

if