15

次のようなnumpy配列を作成しようとしています:

[a b c       ]
[  a b c     ]
[    a b c   ]
[      a b c ] 

したがって、これには主対角線とその上の 2 つの対角線の更新が含まれます。

これを行う効率的な方法は何ですか?

4

5 に答える 5

23

を使用np.indicesして配列のインデックスを取得し、必要な場所に値を割り当てることができます。

a = np.zeros((5,10))
i,j = np.indices(a.shape)

i,jは、それぞれ行インデックスと列インデックスです。

a[i==j] = 1.
a[i==j-1] = 2.
a[i==j-2] = 3.

結果は次のとおりです。

array([[ 1.,  2.,  3.,  0.,  0.,  0.,  0.,  0.,  0.,  0.],
       [ 0.,  1.,  2.,  3.,  0.,  0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  1.,  2.,  3.,  0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  1.,  2.,  3.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  1.,  2.,  3.,  0.,  0.,  0.]])
于 2013-08-02T22:17:42.413 に答える
8

これはToeplitz 行列の例です。次を使用して構築できますscipy.linalg.toeplitz

import numpy as np
from scipy.linalg import toeplitz

first_row = np.array([1, 2, 3, 0, 0, 0])
first_col = np.array([1, 0, 0, 0])

print(toeplitz(first_col, first_row))
# [[1 2 3 0 0 0]
#  [0 1 2 3 0 0]
#  [0 0 1 2 3 0]
#  [0 0 0 1 2 3]]
于 2016-04-23T16:14:00.450 に答える
4
import numpy as np

def using_tile_and_stride():
    arr = np.tile(np.array([10,20,30,0,0,0], dtype='float'), (4,1))
    row_stride, col_stride = arr.strides
    arr.strides = row_stride-col_stride, col_stride
    return arr

In [108]: using_tile_and_stride()
Out[108]: 
array([[ 10.,  20.,  30.,   0.,   0.,   0.],
       [  0.,  10.,  20.,  30.,   0.,   0.],
       [  0.,   0.,  10.,  20.,  30.,   0.],
       [  0.,   0.,   0.,  10.,  20.,  30.]])

その他の遅い代替手段には次のものがあります。

import numpy as np

import numpy.lib.stride_tricks as stride

def using_put():
    arr = np.zeros((4,6), dtype='float')
    a, b, c = 10, 20, 30
    nrows, ncols = arr.shape
    ind = (np.arange(3) + np.arange(0,(ncols+1)*nrows,ncols+1)[:,np.newaxis]).ravel()
    arr.put(ind, [a, b, c])
    return arr

def using_strides():
    return np.flipud(stride.as_strided(
        np.array([0, 0, 0, 10, 20, 30, 0, 0, 0], dtype='float'), 
        shape=(4, 6), strides = (8, 8)))

を使用する場合using_tile_and_stride、配列は読み取り専用の目的にのみ適していることに注意してください。それ以外の場合、配列を変更しようとすると、複数の配列の場所が同時に変更されて驚くかもしれません。

In [32]: arr = using_tile_and_stride()

In [33]: arr[0, -1] = 100

In [34]: arr
Out[34]: 
array([[  10.,   20.,   30.,    0.,  100.],
       [ 100.,   10.,   20.,   30.,    0.],
       [   0.,    0.,   10.,   20.,   30.],
       [  30.,    0.,    0.,   10.,   20.]])

np.ascontiguousarray(arr)の代わりに戻ることでこれを回避できますがarrusing_tile_and_strideよりも遅くなりusing_putます。したがって、配列を変更する場合はusing_put、より良い選択になります。

于 2013-08-02T22:37:15.230 に答える
1

まだコメントすることはできませんが、scipy が処理してくれるので、ali_m の回答が最も効率的であることを強調したいと思います。

たとえば、サイズ の行列を使用して、呼び出しをn,m = 1200繰り返し追加すると、Saullo GP Castro の応答が、およびがかかります。np.diag()~6.14s~7.7sscipy.linalg.toeplitz(np.arange(N), np.arange(N))1.57ms

于 2019-09-02T06:42:37.360 に答える
0

この質問に対する私の答えを使用して、 numpyでマトリックスの対角線の値を変更すると、トリッキーなスライスを実行して各対角線のビューを取得し、割り当てを行うことができます。この場合、次のようになります。

import numpy as np
A = np.zeros((4,6))
# main diagonal
A.flat[:A.shape[1]**2:A.shape[1]+1] = a
# first superdiagonal
A.flat[1:max(0,A.shape[1]-1)*A.shape[1]:A.shape[1]+1] = b
# second superdiagonal
A.flat[2:max(0,A.shape[1]-2)*A.shape[1]:A.shape[1]+1] = c
于 2013-08-02T22:56:28.960 に答える