[英]matrix: move n-th row by n position efficiently
我有一個 numpy 二維數組,我需要以第一行保持不變的方式對其進行轉換,第二行向右移動一個 position (它可以環繞或僅在前面填充零)。 第三行向右移動 3 個位置,依此類推。我可以通過“for 循環”來做到這一點,但這不是很有效。 我猜應該有一個與原始矩陣相乘的過濾矩陣會產生相同的效果,或者可能是一個 numpy 技巧可以幫助我做到這一點? 謝謝。 我已經研究過 numpy.roll() 但我認為它不能單獨在每一行上工作。
import numpy as np
p = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]])
'''
p = [ 1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16]
desired output:
p'= [ 1 2 3 4
0 5 6 7
0 0 9 10
0 0 0 13]
'''
我們可以將滑動 windows 提取到輸入的零填充版本中,以獲得 memory 有效的方法,因此也具有性能。 要獲得這些 windows,我們可以利用基於np.lib.stride_tricks.as_strided
的scikit-image's view_as_windows
。 有關使用基於view_as_windows
的as_strided
的更多信息。
因此,解決方案是 -
from skimage.util.shape import view_as_windows
def slide_by_one(p):
m,n = p.shape
z = np.zeros((m,m-1),dtype=p.dtype)
a = np.concatenate((z,p),axis=1)
w = view_as_windows(a,(1,p.shape[1]))[...,0,:]
r = np.arange(m)
return w[r,r[::-1]]
樣品運行 -
In [60]: p # generic sample of size mxn
Out[60]:
array([[ 1, 5, 9, 13, 17],
[ 2, 6, 10, 14, 18],
[ 3, 7, 11, 15, 19],
[ 4, 8, 12, 16, 20]])
In [61]: slide_by_one(p)
Out[61]:
array([[ 1, 5, 9, 13, 17],
[ 0, 2, 6, 10, 14],
[ 0, 0, 3, 7, 11],
[ 0, 0, 0, 4, 8]])
我們可以利用常規的斜坡模式來獲得更有效的方法,更原始地使用np.lib.stride_tricks.as_strided
,就像這樣 -
def slide_by_one_v2(p):
m,n = p.shape
z = np.zeros((m,m-1),dtype=p.dtype)
a = np.concatenate((z,p),axis=1)
s0,s1 = a.strides
return np.lib.stride_tricks.as_strided(a[:,m-1:],shape=(m,n),strides=(s0-s1,s1))
另一個有一些masking
-
def slide_by_one_v3(p):
m,n = p.shape
z = np.zeros((len(p),1),dtype=p.dtype)
a = np.concatenate((p,z),axis=1)
return np.triu(a[:,::-1],1)[:,::-1].flat[:-m].reshape(m,-1)
這是一個基於零填充和重塑的簡單方法。 它很快,因為它避免了高級索引和其他開銷。
def pp(p):
m,n = p.shape
aux = np.zeros((m,n+m-1),p.dtype)
np.copyto(aux[:,:n],p)
return aux.ravel()[:-m].reshape(m,n+m-2)[:,:n].copy()
您可以使用循環滾動一行並填充 0s
for x in range(p.shape[0]):
p[x] = np.roll(p[x], x)
p[x,0:x] = 0
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.