2017-08-16 69 views
4

我想用一種快速方法爲其分配一個具有布爾評估的函數。這是一個簡單的例子。我想任意ab待評估下列函數:帶有布爾語句的Numpy向量化函數分配

a = 0.5 
b = 0.6 
def func(x): 
    x=max(x,a) 
    if x>b: 
     return x**2 
    else: 
     return x**3 

,然後我想將函數值分配到一個陣列中的矢量方式(速度):

xRange = np.arange(0, 1, 0.1) 
arr_func = func(xRange) 

但我得到的錯誤:

ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

現在,我知道我可以在一個循環中賦值。但與矢量化等價物相比,這將會變得緩慢。我可以繞過這個異常,並仍然以矢量化的方式分配值嗎?

+1

我想你可以使用https://docs.scipy.org/doc/numpy-1.10.0/reference/generated/numpy.vectorize.html – Lukisn

+0

不要在這裏使用'np.vectorize'! –

回答

4

如果我正確地讀你的代碼,這樣做的矢量版本是使用一對夫婦np.where

def func(x): 
    x = np.where(a > x, a, x) 
    return np.where(x > b, x**2, x**3) 
+0

@DanielF - 是的,你可能是對的。但是,這會修改參數(例如在OP的例子中爲'xRange')。這可能並不理想。在這兩種情況下,Numpy已經制作了一大堆副本 - 編寫numpy代碼時(通常是正確的)假設是,與python循環的開銷相比,副本的開銷很小。 – mgilson

+0

真的 - 我很驚訝通過參考不考慮我多考慮多久我會忘記它:)刪除評論,以防止混淆 –

0

如果你想(或有),以保持原來的功能,你可以使用numpy的的vectorize function來創建接受一個numpy數組作爲輸入的「矢量化」版本。

請注意,此功能只是爲了方便,並提供沒有性能改進,因爲它內部只實現for循環。所以沒有「真正的」矢量化!

import numpy as np 

def func(x, a=0.5, b=0.6): 
    x = max(x, a) 
    if x > b: 
     return x**2 
    else: 
     return x**3 

vfunc = np.vectorize(func) # this is it! 

xRange = np.arange(0, 1, 0.1) 
arr_func = vfunc(xRange) 

print(arr_func) 

上面的代碼工作,併產生以下的輸出:

[ 0.125 0.125 0.125 0.125 0.125 0.125 0.36 0.49 0.64 0.81 ] 
+0

這是一個壞主意。您可能需要閱讀['vectorize'](https://docs.scipy.org/doc/numpy/reference/generated/numpy.vectorize.html)文檔頁面的「註釋」部分。 –

+0

謝謝你指出。我編輯了我的答案,以清楚說明。 – Lukisn

2

它也可以使用np.select - 這是在這種情況下不是必要wordier了一點,但可以擴展到很多條件

def func(x): 
    condlist = [ 
        x < a, 
        (x >= a) & (x <= b), 
        x > b 
       ] 
    choicelist = [ 
        a**3, 
        x**3, 
        x**2 
       ] 
    return np.select(condlist, choicelist) 

def func(x): 
    condlist = [ 
        x < a, 
        x > b 
       ] 
    choicelist = [ 
        a**3, 
        x**2 
       ] 
    return np.select(condlist, choicelist, default = x**3)