2016-01-31 99 views
0

假設我有以下列表:高效方式

rays_all = [np.array(r11, r21, r31, r41), 
      np.array(r12, r22, r32, r42), 
      np.array(r13, r23, r33, r43), 
      np.array(r14, r24, r34, r44)] 

所有R11,R21,R31等與形狀陣列(3L,)(認爲它是在載體中3D空間)。

如果我想提取np.array(r14, r24, r34, r44)的(4L,3L)數組,我只是簡單地使用rays_all[-1]。如果我想追加一個np.array(r15, r25, r35, r45)的新數組,我只使用rays_all.append

現在我以另一種方式安排上述載體(R11,R12等):

ray1 = [r11, r12, r13, r14] 
ray2 = [r21, r22] 
ray3 = [r31, r32, r33] 
ray4 = [r41, r42, r43, r44] 

每個「射線」現在具有其自己的列表與不同的長度。如果我想提取數組結構中每個列表的最後一個元素,即np.array([r14,r22,r33,r44]),那麼最有效的方法是什麼?在另一方面,如果我想在陣列np.array([r15,r23,r34,r45])中添加元素到列表中,這樣我會有

ray1 = [r11, r12, r13, r14, r15] 
ray2 = [r21, r22, r23] 
ray3 = [r31, r32, r33, r34] 
ray4 = [r41, r42, r43, r44, r45] 

什麼是最有效的方法是什麼?我知道我可以做一個循環來做,但我想它比rays_all[-1]rays_append()慢得多?有沒有「矢量化」的方式來做到這一點?

+0

通常很難獲得未對齊數據的矢量化優勢。數組實現可能不會改進自然列表算法。 –

+0

所以在這種情況下使用循環已經是最快的方法了?是否還有其他方式存儲ray1,ray2,ray3,ray4(使它們對齊?),以便我仍然可以使用rays_all矢量化方式? – Physicist

+0

爲這些列表定義'align'? – hpaulj

回答

1

小心混合數組和列表操作。

使一些3元件陣列和其組合作爲你第一種情況:

In [748]: r1,r2,r3,r4=np.arange(3),np.ones(3),np.zeros(3),np.arange(3)[::-1] 
In [749]: x1=np.array((r1,r2)) 
In [750]: x2=np.array((r3,r4)) 
In [751]: rays=[x1,x2] 
In [752]: rays 
Out[752]: 
[array([[ 0., 1., 2.], 
     [ 1., 1., 1.]]), array([[ 0., 0., 0.], 
     [ 2., 1., 0.]])] 

rays現在是一個列表包含兩個2D陣列((2,3)的形狀)。正如你所說,你可以從列表中選擇一個項目或附加另一個數組(你可以附加任何東西,而不僅僅是一個類似的數組)。 rays的操作是列表操作。

你也可以創建一個三維數組:

In [758]: ray_arr=np.array((x1,x2)) 
In [759]: ray_arr 
Out[759]: 
array([[[ 0., 1., 2.], 
     [ 1., 1., 1.]], 

     [[ 0., 0., 0.], 
     [ 2., 1., 0.]]]) 
In [760]: ray_arr.shape 
Out[760]: (2, 2, 3) 
In [761]: ray_arr[-1] 
Out[761]: 
array([[ 0., 0., 0.], 
     [ 2., 1., 0.]]) 

您可以從ray_arr與列表中進行選擇。但是追加需要通過np.concatenate(可能隱藏在np.append函數中)創建一個新數組。沒有「就地」附加在列表上。

通過索引最後一個維度,有效選擇所有組件陣列的最後一個元素。

In [762]: ray_arr[:,:,-1] 
Out[762]: 
array([[ 2., 1.], 
     [ 0., 0.]]) 

要從列表rays你有一個列表理解(或其他循環)得到相應的值:

In [765]: [r[:,-1] for r in rays] 
Out[765]: [array([ 2., 1.]), array([ 0., 0.])] 

有沒有索引的快捷與陣列。

工具有zip(以及itertools中的其他工具),它們可以幫助您遍歷列表,甚至重新排列值(例如,

In [773]: list(zip(['a','b'],['c','d'])) 
Out[773]: [('a', 'c'), ('b', 'd')] 
In [774]: list(zip(['a','b'],['c','d']))[-1] 
Out[774]: ('b', 'd') 

與衣衫襤褸的子列表:

In [782]: list(zip(['a','b','c'],['d'])) 
Out[782]: [('a', 'd')] 
In [783]: list(itertools.zip_longest(['a','b','c'],['d'])) 
Out[783]: [('a', 'd'), ('b', None), ('c', None)] 

但我看不出那些會從你的射線向量提取值的幫助。


東西值得探討是收集基矢量成一個二維數組,並使用索引以用於各種目的的額外基團,

In [867]: allrays=np.array([r1,r2,r3,r4]) 
In [868]: allrays 
Out[868]: 
array([[ 0., 1., 2.], 
     [ 1., 1., 1.], 
     [ 0., 0., 0.], 
     [ 2., 1., 0.]]) 

的「Z」 COOR對所有光線

In [869]: allrays[:,-1] 
Out[869]: array([ 2., 1., 0., 0.]) 

射線的一個子集(因爲它是一個切片它是一個視圖)

In [871]: allrays[0:2,:] 
Out[871]: 
array([[ 0., 1., 2.], 
     [ 1., 1., 1.]]) 

另一個亞類:

In [872]: allrays[2:,:] 
Out[872]: 
array([[ 0., 0., 0.], 
     [ 2., 1., 0.]]) 

3項子集,具有列表中選擇 - 這是一個拷貝由索引獲得

In [873]: allrays[[0,1,2],:] 
Out[873]: 
array([[ 0., 1., 2.], 
     [ 1., 1., 1.], 
     [ 0., 0., 0.]]) 
In [874]: allrays[[3],:] 
Out[874]: array([[ 2., 1., 0.]]) 

幾個子集:

In [875]: ind=[[0,1,2],[3]] 
In [876]: [allrays[i] for i in ind] 
Out[876]: 
[array([[ 0., 1., 2.], 
     [ 1., 1., 1.], 
     [ 0., 0., 0.]]), 
array([[ 2., 1., 0.]])] 

如果基團是連續的,你可以使用split

In [884]: np.split(allrays,[3]) 
Out[884]: 
[array([[ 0., 1., 2.], 
     [ 1., 1., 1.], 
     [ 0., 0., 0.]]), array([[ 2., 1., 0.]])] 

該子排列是意見(與.__array_interface__屬性檢查。

它實際上只是將不規則列表問題提高一級。不過,還有更多的靈活性。您可以構建其他索引子列表,例如

In [877]: ind1=[i[-1] for i in ind] # last of all groups 
In [878]: ind1 
Out[878]: [2, 3] 
In [879]: ind2=[i[0] for i in ind] # first of all groups 
In [880]: ind2 
Out[880]: [0, 3] 

您可以連接一些新的值到allrays。然後您可能必須重建索引列表。但我懷疑這種建築是完成了一次,而訪問重複。


較早SO質疑大約從由plt.pcolormesh(和plt.pcolor)中產生的img訪問值想到。一個將圖像保持爲二維網格上的曲面,另一個更一般,只是四邊形的集合,每個四邊形都有一個顏色和路徑來定義其邊界。

1

在回答您的具體問題,包含四個「雷人」名單的最後一個元素的列表,在一般[ray1[-1],ray2[-1],ray3[-1],ray4[-1]]

由於您在這裏的主要關注似乎是執行速度,我假設您必須反覆執行此操作。你有沒有考慮建立一個代表最後一個元素,說,last_element = [r1x,r2x,r3x,r4x]和維護它的價值,你通過這個問題步驟一點點數據結構?每次更改last_element時,都會根據需要將新數據附加到其他列表中。換句話說,而不是重複地從大名單中提取的最後一個元素,打造大名單一步一步從最後一個元素。這將需要更有效,只要你有反正建那些大名單。它會對你的問題起作用嗎?