[[ 0.0 0.2 0.4 0.6 ]
[ 0.0 0.0 2.0 4.0 6.0 ]
[ 0.0 0.0 0.0 20.0 40.0 60.0 ]]
是一個衣衫襤褸的名單。我們可以用viectorized陣列魔法來構建它,至少不是用普通的東西。
爲了解決這個問題,我們需要或者變平或墊這種結構
[[ 0.0 0.2 0.4 0.6 0.0 0.0]
[ 0.0 0.0 2.0 4.0 6.0 0.0 ]
[ 0.0 0.0 0.0 20.0 40.0 60.0 ]]
或
[ 0.0 0.2 0.4 0.6 0.0 0.0 2.0 4.0 6.0 0.0 0.0 0.0 20.0 40.0 60.0 ]
sum.reduceat
讓我們平坦的陣列的總和塊,但你想跳過總和。我想我可以探索平移轉置。
我的第一個想法是,填充陣列看起來像是一個對角化陣列,[.2,2,20]放置在對角線上,在下一個偏移處放置[.4,4,40],等等。 。我知道sparse
可以從一個矩陣和一組偏移量構建矩陣,但我不認爲在numpy
中有這樣的函數。他們一次只能使用一個膠印。
但它也看起來像stride_tricks
可以產生的偏移類型。
讓我們探索:
In [458]: as_strided =np.lib.index_tricks.as_strided
In [459]: Z=np.pad(z,[[0,0],[3,3]],mode='constant')
In [460]: Z
Out[460]:
array([[ 0. , 0. , 0. , 0.2, 0.4, 0.6, 0. , 0. , 0. ],
[ 0. , 0. , 0. , 2. , 4. , 6. , 0. , 0. , 0. ],
[ 0. , 0. , 0. , 20. , 40. , 60. , 0. , 0. , 0. ]])
In [461]: Z.strides
Out[461]: (72, 8) # prod an offset with (72+8, 8)
In [462]: as_strided(Z,shape=(3,6),strides=(80,8))
Out[462]:
array([[ 0. , 0. , 0. , 0.2, 0.4, 0.6],
[ 0. , 0. , 2. , 4. , 6. , 0. ],
[ 0. , 20. , 40. , 60. , 0. , 0. ]])
這就是那種我們想要轉移的,但方向是錯誤的;所以讓翻蓋Z
:
In [463]: Z1=Z[::-1,:].copy()
In [464]: as_strided(Z1,shape=(3,6),strides=(80,8))
Out[464]:
array([[ 0. , 0. , 0. , 20. , 40. , 60. ],
[ 0. , 0. , 2. , 4. , 6. , 0. ],
[ 0. , 0.2, 0.4, 0.6, 0. , 0. ]])
In [465]: as_strided(Z1,shape=(3,6),strides=(80,8)).sum(0)
Out[465]: array([ 0. , 0.2, 2.4, 24.6, 46. , 60. ])
泛化可以留給讀者。
是否有任何速度優勢未知。可能不是這個小案子,也許是一個非常大的案件。
此清理填充和跨越位
In [497]: Z=np.pad(z,[[0,0],[1,4]],mode='constant')
In [498]: Z.strides
Out[498]: (64, 8)
In [499]: as_strided(Z,shape=(3,6),strides=(64-8,8))
Out[499]:
array([[ 0. , 0.2, 0.4, 0.6, 0. , 0. ],
[ 0. , 0. , 2. , 4. , 6. , 0. ],
[ 0. , 0. , 0. , 20. , 40. , 60. ]])
這忽略z
是如何構造的。如果外部產品是問題的核心,我可能會嘗試在1d y
上大步前進,並使用x
執行加權求和。
In [553]: x=np.array([1,10,100]); y=np.array([.2,.4,.6])
In [554]: z=np.concatenate(([0,0],y[::-1],[0,0,0]))
In [555]: z
Out[555]: array([ 0. , 0. , 0.6, 0.4, 0.2, 0. , 0. , 0. ])
In [556]: Z=as_strided(z,shape=(3,6), strides=(8,8))
In [557]: Z
Out[557]:
array([[ 0. , 0. , 0.6, 0.4, 0.2, 0. ],
[ 0. , 0.6, 0.4, 0.2, 0. , 0. ],
[ 0.6, 0.4, 0.2, 0. , 0. , 0. ]])
In [558]: np.dot(x,Z)
Out[558]: array([ 60. , 46. , 24.6, 2.4, 0.2, 0. ])
在這種結構中Z
是z
的圖,所以是比上的Z
小。但我確信dot
將它發送到編譯代碼時會生成副本。 np.einsum('i,ij',x,Z)
可能會避免這種情況,在不擴展它的情況下對其進行編譯迭代。處理非常大的數組時,這可能會有所不同。
結果相反,但這很容易修復。我甚至可以在施工期間修復它。
小心時間測試。非迭代答案會創建一個數組,其大小是原始數據的兩倍。迭代地,您可以在沒有這些的情況下對偏移行進行求和。 – hpaulj
「外部」是問題的重要組成部分,還是創建'z'的便捷方式?這真的是某種內在產品或加權移動總和? – hpaulj