2010-12-21 75 views
9

的numpy的vectorize功能非常有用,但它並沒有表現良好時,函數的參數是列表而不是標量。舉個例子:NumPy的矢量化,使用列表作爲參數

import numpy as np 

def f(x, A): 
    print "type(A)=%s, A=%s"%(type(A),A) 
    return sum(A)/x 

X = np.linspace(1,2,10) 
P = [1,2,3] 

f2 = np.vectorize(f) 

f(X,P) 
f2(X,P) 

給出:

type(A)=<type 'list'>, A=[1, 2, 3] 
type(A)=<type 'numpy.int64'>, A=1 

Traceback (most recent call last): 
    File "vectorize.py", line 14, in <module> 
    f2(X,P) 
    File "/usr/local/lib/python2.6/dist-packages/numpy/lib/function_base.py", line 1824, in __call__ 
    theout = self.thefunc(*newargs) 
    File "vectorize.py", line 5, in f 
    return sum(A)/x 
TypeError: 'numpy.int64' object is not iterable 

據我瞭解,函數f工作就好沒有vectorize荷蘭國際集團,但我想知道如何(一般)矢量化一個函數,其參數採用列表而不是標量。

回答

11

你的問題沒有說清楚正是你想什麼輸出從量化的功能看,但我會假設你想在同一目錄(A)採用作爲參數到f的每次調用( )(例如,對於X數組中的每個元素一次)

函數的矢量化版本確保所有參數都是數組,然後應用numpy's broadcasting rules來確定如何組合這些參數。

與np.array的np.ndarray包裝一樣,通過自動將列表轉換爲包含相同元素的數組,而不是使用dtype = object創建數組,該數組的參數強制嘗試有幫助。包含該列表作爲其唯一元素。這其中大部分的時間是我們所希望的,但在你的情況下,這種「聰明」的行爲是回來咬你。

雖然可能有指示numpy的只有一種方式對待某些輸入向量,有兩種簡單的方式來獲得你後的行爲:

  1. 手動創建一個array with dtype=object在廣播內工作規則
  2. Curry矢量化功能

1 = D型對象

之前的值

numpy的陣列獲得它們的效率從僅將存儲一種類型的項目,但它們仍然可以通過指定所存儲的數據類型是蟒對象包含任意Python對象:

list_obj_array = np.ndarray((1,), dtype=object) 
list_obj_array[0] = [1,2,3] 
f2(X,list_obj_array) # using your definition from above 

打印:

type(A)=<type 'list'>, A=[1, 2, 3] 
type(A)=<type 'list'>, A=[1, 2, 3] 
type(A)=<type 'list'>, A=[1, 2, 3] 
type(A)=<type 'list'>, A=[1, 2, 3] 
type(A)=<type 'list'>, A=[1, 2, 3] 
type(A)=<type 'list'>, A=[1, 2, 3] 
type(A)=<type 'list'>, A=[1, 2, 3] 
type(A)=<type 'list'>, A=[1, 2, 3] 
type(A)=<type 'list'>, A=[1, 2, 3] 
type(A)=<type 'list'>, A=[1, 2, 3] 
type(A)=<type 'list'>, A=[1, 2, 3] 

返回:

array([ 6.  , 5.4  , 4.90909091, 4.5  , 4.15384615, 
     3.85714286, 3.6  , 3.375  , 3.17647059, 3.  ]) 

2。

def curry_f(A): 
    def f_curried(x): 
     return f(x, A) # using your definition from above 
    return f_curried 

f2 = np.vectorize(curry_f(P)) 
f2(X) 

打印:鑽營

因爲你是通過相同的列表來調用函數的每個項目在數組中,你可以直接與功能應用矢量之前討好存儲列表

type(A)=<type 'list'>, A=[1, 2, 3] 
type(A)=<type 'list'>, A=[1, 2, 3] 
type(A)=<type 'list'>, A=[1, 2, 3] 
type(A)=<type 'list'>, A=[1, 2, 3] 
type(A)=<type 'list'>, A=[1, 2, 3] 
type(A)=<type 'list'>, A=[1, 2, 3] 
type(A)=<type 'list'>, A=[1, 2, 3] 
type(A)=<type 'list'>, A=[1, 2, 3] 
type(A)=<type 'list'>, A=[1, 2, 3] 
type(A)=<type 'list'>, A=[1, 2, 3] 

和回報:

array([ 6.  , 5.4  , 4.90909091, 4.5  , 4.15384615, 
     3.85714286, 3.6  , 3.375  , 3.17647059, 3.  ]) 

P.S.你也可以看看np.frompyfunc - 它與vectorize()類似,但是它的工作方式稍低一些。

0

這是我目前使用矢量化一個函數,一維數組作爲第一個參數遞歸裝飾的例子:

def broadcast(fvec): 
    def inner(vec, *args, **kwargs): 
     if len(vec.shape) > 1: 
      return np.array([inner(row, *args, **kwargs) for row in vec]) 
     else: 
      return fvec(vec, *args, **kwargs) 
    return inner 

我猜它幾乎一樣np.vectorize,但對我來說,使用這項工作比嘗試改編vectorize/frompyfunc更容易。