2016-05-29 51 views
2

我想根據一個數組中的值是否在另一個數組中創建一個數組。我希望下面將工作:np.fromfunction:引用其他數組

A = np.fromfunction(lambda x, y: tuple(order[x,:]) in paths[y,],\ 
    shape=((len(order), len(paths))), dtype=int) 

不幸的是,這只是產生一個標量值,而不是陣列我想要的。我可以通過如下方法對for循環做同樣的處理,但是由於涉及的值很多,這個選項非常慢。

A = np.zeros(shape=(len(order), len(paths)), dtype=int) 
for i in np.ndindex(len(order), len(paths)): 
    r = i[0] # Row 
    c = i[1] # Column 
    x = r + c + (len(paths)-1)*r 
    if paths[c,] == None: 
     pass 
    elif tuple(order[r,:]) in paths[c,]: 
     np.put(A, x, 1, 'wrap') 

有沒有人有一種有效的方式來生成目標矩陣?非常感謝你的幫助!

\編輯:非常感謝您的提示hpaulj。我認爲np.where走向我想要實現的方向,但無法處理這兩個陣列的複雜性。我編輯了上面的方法,因爲x = r*c if r*c != 0 else r+c沒有給我我想要的結果 - 當我的輸出是亂碼時,我不知何故地發現了它... x = r + c + (len(paths)-1)*r確實可以唯一地標識flattend 2D數組的每個位置。我在下面列出了一些樣本,這些樣本應該能夠讓我更清楚自己想要實現的目標。對困惑感到抱歉!

order 
[[ 73 6 3 1] 
[ 73 6 3 2] 
[ 6 116 3 1] 
[ 6 116 3 2] 
[116 45 3 1] 
...10k additional lines...] 

paths 
[ [(12, 14, 1615, 1), (14, 156, 1615, 1), (156, 83, 1615, 1), (83, 37, 1554, 1), (37, 36, 1554, 1)] 
    [(12, 14, 1615, 2), (14, 156, 1615, 2), (156, 83, 1615, 2), (83, 37, 1554, 2), (37, 36, 1554, 2)] 
    [(12, 14, 1615, 1), (14, 156, 1615, 1), (156, 83, 1615, 1), (83, 37, 1554, 1), (37, 36, 1554, 1)] 
    [(12, 14, 1615, 2), (14, 156, 1615, 2), (156, 83, 1615, 2), (83, 37, 1554, 2), (37, 36, 1554, 2)] 
    [(12, 14, 1615, 1), (14, 156, 1615, 1), (156, 83, 1615, 1), (83, 37, 1554, 1), (37, 36, 1554, 1)] 
    [(12, 14, 1615, 2), (14, 156, 1615, 2), (156, 83, 1615, 2), (83, 37, 1554, 2), (37, 36, 1554, 2)] 
    ...600 additional lines...] 

的目標是檢查每個order值是否是內paths並且將其置於一個True1在行/列交叉點的。所有其他交叉口應該是False/0。保持行和列的順序非常重要,因爲矩陣然後與有序向量相乘。實際上,我正在對此進行模擬(URL--見下文,p94)算法。該矩陣應該反映特定產品(paths)對特定資源(order)的利用率。

網址:https://books.google.com/books?id=GhdDbEM-_5oC&lpg=PA100&ots=wH5OVDz7JV&dq=dlp%20revenue%20management&pg=PA94#v=onepage&q&f=false

回答

2

看代碼的形式fromfunction

args = indices(shape, dtype=dtype) 
return function(*args,**kwargs) 

np.indices就像meshgrid

In [28]: np.indices((2,3)) 
Out[28]: 
array([[[0, 0, 0], 
     [1, 1, 1]], 

     [[0, 1, 2], 
     [0, 1, 2]]]) 

所以np.fromfunction(lambda i, j: i + j, (3, 3), dtype=int)是做

In [29]: idn=np.indices((2,3)) 
In [31]: idn[0]+idn[1] 
Out[31]: 
array([[0, 1, 2], 
     [1, 2, 3]]) 

相當於哪我通常用廣播做:np.arange(2)[:,None] + np.arange(3)

有一個np.frompyfunc,它會將Python函數應用於其輸入的每個元素。但它只適用於1d(儘管圍繞結構化數組有一些巧妙的技巧)。 np.vectorize也使用這個。但兩者仍在迭代,所以節省的時間至多是2倍。

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

ndindex是生成索引的另一種方式值

In [42]: list(np.ndindex(2,3)) 
Out[42]: [(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2)] 

In [43]: list(zip(*np.ndindex(2,3))) 
Out[43]: [(0, 0, 0, 1, 1, 1), (0, 1, 2, 0, 1, 2)] 

隨着zip轉置我得到類似於由產生的值nd.indices(但發生了變化)。

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

沒有爲orderpaths樣本值很難想象你的函數正在做什麼。或者說,只是通過閱讀代碼,我無法瞭解它在做什麼,沒有樣本,我無法進行測試。對於採用標量i,j座標的「黑盒子」函數,您的方法大致如此。爲了使速度更快,您必須重新修改該函數,以便直接使用np.indices的子陣列,而不是迭代地使用。

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

一個量化的方法,讓你的x值可以是

In [105]: I,J=np.indices((3,3)) 

In [106]: np.where(I*J,I*J,I+J) 
Out[106]: 
array([[0, 1, 2], 
     [1, 1, 2], 
     [2, 2, 4]]) 

where執行整個陣列上的x = r*c if r*c != 0 else r+c

與布爾掩蔽(的好工具陣列if測試)同樣的事情是:

In [114]: x=I*J 

In [115]: mask = x==0 

In [116]: x[mask]=(I+J)[mask] 

In [117]: x 
Out[117]: 
array([[0, 1, 2], 
     [1, 1, 2], 
     [2, 2, 4]])