2012-02-09 78 views
1

我在尋找一種高效優雅的方式來做到這一點。我希望這個例子能夠解釋我的擔憂。numpy slice assignment

我們已經有了一個np.array這樣的:

omega = np.array([1.03415121504, 1.29595060284, 1.55774999064, 1.81954937844, 
        ... 
        2.08134876623, 2.37359445321, -2.11179506541, -1.84999567761]) 

,現在我想操縱它,就像

omega[omega < 0.0] = omega + 2 * np.pi 
omega[omega >= 2 * np.pi] = omega - 2 * np.pi 

第二條語句可以覆蓋拳頭聲明的計算值,然後有一個十字路口。我發現np.piecewise,但是這不提供這樣的行爲。

我該如何達到這個效率?

的corrent行爲是這樣的(但很效率不高/不雅):

tmp = [] 
for o in omega: 
    if o < 0.0: 
     tmp.append(o + 2 * np.pi) 
    elif o >= (2 * np.pi): 
     tmp.append(o - 2 * np.pi) 
    else: 
     tmp.append(o) 
omega = np.array(tmp) 

因此有人提出用numpy的的nditer用於上述目的的經歷? (尤其是性能/效率)

+1

你是否意識到歐米加奧米加= 0 + 2 * np.pi'有點奇怪?你可能意指'歐米茄[歐米茄<0.0] + = 2 * np.pi'。 (第一種形式爲'omega'的所有元素添加'2 * np.pi',然後使用這個新數組中的第一個條目作爲'omega'的第一個否定條目的值 - 值變得很奇怪) – 2012-02-09 15:34:29

+0

@SvenMarnach哇,當你用2d或3d數組做它時,它會給出一個錯誤,「數組不能廣播以糾正形狀」,當你做omega [:] = wrong_size_array時,它會給出一個錯誤,所以它有點奇怪的是,1d布爾索引案例不檢查不匹配。 – 2012-02-09 18:00:07

+0

@Bago:這種行爲實際上是記錄在案的。它有時是有用的,但對於更高維度沒有有用的概括。 – 2012-02-09 18:11:01

回答

3

你可以嘗試使用np.selecthttp://docs.scipy.org/doc/numpy/reference/generated/numpy.select.html

condlist = [omega < 0.0, omega >= 2.0*np.pi] 
choicelist = [omega + 2.0*np.pi, omega - 2.0*np.pi] 
omega = np.select(condlist,choicelist,default=omega) 
+0

這很方便,雖然它的缺點是做了比必要的更多的計算。如果這不是瓶頸,但它可以很好地工作。 – DSM 2012-02-09 15:42:03

2

第二條語句可能會覆蓋第一條語句的計算值。

這是沒有辦法發生的。如果是前小於零,添加2*pi絕不會讓它大於或等於2*pi

無論如何,一個簡單的方法來實現你想要的可能是什麼

omega %= 2 * np.pi 
+0

我的例子不夠詳盡,我有幾個這樣的結構,有兩個以上的表達式。有沒有一種通用的方法來避免帶切片的for-loop,沒有競態條件?你的代碼工作(謝謝!),但上面的例子產生錯誤的值。 – Themerius 2012-02-09 15:31:21

2

我建議做對指數的計算:

i = omega < 0.0 
omega[i] += 2*np.pi 
i = (~i) & (omega >= 2 * np.pi) 
omega[i] -= 2*np.pi 

第三行中的按位邏輯操作可確保不會使用兩次索引。從你給出的例子來看,Sven Marnach的模解答更有效率。如果你有更復雜的用例,你應該更新你的問題。