2014-09-04 41 views
3
import numpy as np 
bc = np.arange(10) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 

# regular way using NumPy function 
np.diff(bc) # array([1, 1, 1, 1, 1, 1, 1, 1, 1]) 

# something similar with array subtraction: 
bc[1:] - bc[:-1] # array([1, 1, 1, 1, 1, 1, 1, 1, 1]) 

# but this does the wrong thing: 
bc[1:] -= bc[:-1] # array([0, 1, 1, 2, 2, 3, 3, 4, 4, 5]) 

作爲C和C++程序員,我能理解爲什麼會這樣(它的的memcpy()代替的memmove()一遍),但它似乎像Python的最終用戶NumPy可能不會期望這一點。我沒有找到任何文件說這不起作用。NumPy的:錯誤的結果修改數組時使用本身

的問題是:是否有與NumPy的錯誤在這裏(可能不是),或者是有一些NumPy的文件,說明規則是什麼在這樣的情況下,或者是從文檔丟失?

其次,我想找出一個安全,工作液是在空間和時間準優化。也就是說,它不應該分配超出常量的內存,它不應該是一個愚蠢的純Python「for」循環。 :)這些是人們可能希望通過就地修改實現的目標,而這顯然不起作用。

我使用NumPy的1.8.0。

+0

內部'diff'使用相同的切片區別。切片不使用任何額外的內存。唯一添加的內存用於輸出。由於輸出具有與輸入不同的大小,因此我不認爲需要位置差異(尤其是如果diff步長大於1)。 – hpaulj 2014-09-04 21:38:14

+1

'np.subtract(bc [1:],bc [: - 1],out = bc [: - 1])'產生[1,1,1,1,1,1,1,1, 9]' - 期望的區別,除了不變的期限在最後。 – hpaulj 2014-09-04 22:00:41

回答

0

我發現張貼這個問題,在進行一些討論。搜索的重要術語是「切片」。它在這裏:http://numpy-discussion.10968.n7.nabble.com/Strange-behavior-in-setting-masked-array-values-in-Numpy-1-1-0-td11999.html

在頁面中部分有關於試圖檢測和警告這類事情的討論,但這聽起來像是一個失敗的原因。所以我開始尋找另一種就地方法來做我想做的事情。這裏是!

bc[-1:0:-1] -= bc[-2::-1] 

感謝@fredtantini爲明確寫出來的純Python 「for」 循環這NumPy的有效呢。這讓我想到了如何用純Python修復它(反向迭代!),這導致了上述解決方案。

+3

嚴重的是,在你做這種危險的伎倆之前......返回一個新數組的非內置版本可能同樣快,因爲分配一個數組並不是那麼糟糕,而是以更好的方式進行。 – seberg 2014-09-04 10:58:58

+0

我不認爲這種方法是危險的。你做?如果是這樣,可能會出現什麼問題?無論如何,分配一個新的數組是通常的阻力最小的路徑,但是如果數組的大小是幾千兆字節,它將不會真正起作用。 :) – 2014-09-04 11:16:33

+0

如果numpy的開發人員改變數組的迭代方式,這可能會很危險。例如,大多數'memcpy'實現「向前複製」,但並不要求他們這樣做。 numpy規範是否可以保證迭代次序? – 2014-09-04 14:21:05

0

我不認爲這是一個錯誤:
bc[1:] -= bc[:-1]你正在修改列表,同時進行操作。

的過程就像是

for i in range(1,len(bc)): 
    bc[i] = bc[i] - bc[i-1] 

所以下一步bc[i-1]修改:

"i"  1 
bc[1:]: 1,2,3,4,5,… 
bc[:-1]: 0,1,2,3,4,5,… 
bc[1]= 1 - 0 = 1 
new bc: 0,1,2,3,4,5,… 

"i"  2 
bc[1:]: 1,2,3,4,5,… 
bc[:-1]: 0,1,2,3,4,5,… 
bc[2]= 2 - 1 = 1 
new bc: 0,1,1,3,4,5,… 


"i"   3 
bc[1:]: 1,1,3,4,5,… 
bc[:-1]: 0,1,1,3,4,5,… 
bc[1]= 3 - 1 = 2 
new bc: 0,1,1,2,4,5,… 


"i"   4 
bc[1:]: 1,1,2,4,5,… 
bc[:-1]: 0,1,1,2,4,5,… 
bc[1]= 4 - 2 = 2 
new bc: 0,1,1,2,2,5,… 

等等等等。

對於這個問題的其餘部分,我不能回答。

+0

是的,我明白這一點。我的問題是在我的帖子的底部說明的......即是否是徹頭徹尾的錯誤,或是否在某個地方有記錄,如果它不是一個錯誤,如果有一些安全的公式是準最佳的空間和時間。 – 2014-09-04 08:47:06

1

林張貼在這裏再次糾正我的答案。 也許嘗試:

bc-=np.roll(bc , 1) 

#array([-9, 1, 1, 1, 1, 1, 1, 1, 1, 1]) 
#this arrays length is 10 

#and then for an array with length 9 
bc=bc[ 1 : ] 

#array([1, 1, 1, 1, 1, 1, 1, 1, 1]) 

對不起小姐,瞭解面臨的問題,

的結果的原因:

'array([0, 1, 1, 2, 2, 3, 3, 4, 4, 5])' 

,這一行動實際上是syntaxed爲扣的

let (say...) a=array([0,1,2,3,4,5,6,7,8,9]) 
updated a <- will be formed as [0, 1-0=1,2-1=1,3-1=2,4-2=2,5-2=3,6-3=3,7-3=4,8-4=4,9-4=5] 

我想你真正想要的是上述

TNX EdChum