2017-10-01 5 views
2

私は以下のような行数の行列を持っています。行ベクトルからブロック行列を作成する最適な方法は何ですか?

X = np.array([1,2,3]) 

私は次のようにブロック行列を作成したい:

1 0 0 
2 1 0 
3 2 1 
0 3 2 
0 0 3 

は、どのように私はこのnumpyの使用して行うことができますか?

+0

これら2つの関係は何ですか?畳み込み? –

+3

最後の要素(row-5、col-3)は本当に '1'ですか? – Divakar

+1

おそらくhttps://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.roll.htmlを試してください –

答えて

1

アプローチ#1:np.lib.stride_tricks.as_strided使用 -

from numpy.lib.stride_tricks import as_strided as strided 

def zeropad_arr_v1(X): 
    n = len(X) 
    z = np.zeros(len(X)-1,dtype=X.dtype) 
    X_ext = np.concatenate((z, X, z)) 

    s = X_ext.strides[0] 
    return strided(X_ext[n-1:], (2*n-1,n), (s,-s), writeable=False) 

これにより、read-onlyという出力が生成されることに注意してください。後で書き込む必要がある場合は、末尾に.copy()を追加してコピーを作成するだけです。

アプローチ#2:ゼロで連結を使用し、次いでクリッピング/スライシング - ストライドベースの方法である

def zeropad_arr_v2(X): 
    n = len(X) 
    X_ext = np.concatenate((X, np.zeros(n,dtype=X.dtype))) 
    return np.tile(X_ext, n)[:-n].reshape(-1,n,order='F') 

アプローチ#1は、パフォーマンス上の非常に効率的であるべきです。

サンプルの実行 -

In [559]: X = np.array([1,2,3]) 

In [560]: zeropad_arr_v1(X) 
Out[560]: 
array([[1, 0, 0], 
     [2, 1, 0], 
     [3, 2, 1], 
     [0, 3, 2], 
     [0, 0, 3]]) 

In [561]: zeropad_arr_v2(X) 
Out[561]: 
array([[1, 0, 0], 
     [2, 1, 0], 
     [3, 2, 1], 
     [0, 3, 2], 
     [0, 0, 3]]) 

ランタイムテスト

In [611]: X = np.random.randint(0,9,(1000)) 

# Approach #1 (read-only) 
In [612]: %timeit zeropad_arr_v1(X) 
100000 loops, best of 3: 8.74 µs per loop 

# Approach #1 (writable) 
In [613]: %timeit zeropad_arr_v1(X).copy() 
1000 loops, best of 3: 1.05 ms per loop 

# Approach #2 
In [614]: %timeit zeropad_arr_v2(X) 
1000 loops, best of 3: 705 µs per loop 

# @user8153's solution 
In [615]: %timeit hstack_app(X) 
100 loops, best of 3: 2.26 ms per loop 
2

希望する出力マトリクスをトップダウンしてから左右に読み取ると、パターン1,2,3,0,0,0,1,2,3,0,0,0,1,3が表示されます。 2,3。あなたは簡単にリニアアレイを作成するには、そのパターンを使用して、2次元状にそれを再構築することができます

import numpy as np 
X = np.array([1,2,3]) 
N = len(X) 
zeros = np.zeros_like(X) 
m = np.hstack((np.tile(np.hstack((X,zeros)),N-1),X)).reshape(N,-1).T 
print m 

が与える

[[1 0 0] 
[2 1 0] 
[3 2 1] 
[0 3 2] 
[0 0 3]] 
1

他の書き込み可能な解決策:

def block(X): 
    n=X.size 
    zeros=np.zeros((2*n-1,n),X.dtype) 
    zeros[::2]=X 
    return zeros.reshape(n,-1).T 

試してみてください。

In [2]: %timeit block(X) 
600 µs ± 33 µs per loop (mean ± std. dev. of 7 runs, 100 loops each) 
関連する問題