web-dev-qa-db-ja.com

scipy.sparse行列の拡張(行または列の追加)

Scipy.sparseからNxN行列M(lil_matrixまたはcsr_matrix)があり、それを(N + 1)xNにしたいとします。ここで、M_modified [i、j] = M [i、j]は0 <= i <Nに対して(およびすべてのj)およびすべてのjに対してM [N、j] = 0。基本的に、Mの最下部にゼロの行を追加し、行列の残りを保持します。データをコピーせずにこれを行う方法はありますか?

31
RandomGuy

コピーから逃れる方法はないと思います。これらの両方のタイプのスパース行列は、データをNumpy配列として(csrのデータとインデックスの属性、lilのデータと行の属性に)内部に格納し、Numpy配列は拡張できません。

詳細情報で更新:

LILはLInked Listの略ですが、現在の実装はその名前に完全には対応していません。 datarowsに使用されるNumpy配列は両方ともオブジェクト型です。これらの配列の各オブジェクトは、実際にはPythonリスト(すべての値が連続してゼロの場合は空のリスト)です)Pythonリストは正確にリンクされていませんリストですが、それらはO(1)ルックアップのため、非常に近いものであり、率直に言って良い選択です。個人的には、オブジェクトのNumpy配列を使用する意味がすぐにはわかりませんPythonリストではなく、ここで。現在のlil実装を変更して、Pythonリストを使用するように簡単に変更できます。これにより、コピーせずに行を追加できます。マトリックス全体。

6
Justin Peel

Scipyには、データをコピーせずにこれを行う方法はありませんが、疎行列を定義する属性を変更することで、自分で行うことができます。

Csr_matrixを構成する4つの属性があります。

data:マトリックスの実際の値を含む配列

インデックス:データの各値に対応する列インデックスを含む配列

indptr:各行のデータの最初の値の前のインデックスを指定する配列。行が空の場合、インデックスは前の列と同じです。

shape:マトリックスの形状を含むタプル

ゼロの行を下に追加するだけの場合は、マトリックスの形状とindptrを変更するだけです。

x = np.ones((3,5))
x = csr_matrix(x)
x.toarray()
>> array([[ 1.,  1.,  1.,  1.,  1.],
          [ 1.,  1.,  1.,  1.,  1.],
          [ 1.,  1.,  1.,  1.,  1.]])
# reshape is not implemented for csr_matrix but you can cheat and do it  yourself.
x._shape = (4,5)
# Update indptr to let it know we added a row with nothing in it. So just append the last
# value in indptr to the end.
# note that you are still copying the indptr array
x.indptr = np.hstack((x.indptr,x.indptr[-1]))
x.toarray()
array([[ 1.,  1.,  1.,  1.,  1.],
       [ 1.,  1.,  1.,  1.,  1.],
       [ 1.,  1.,  1.,  1.,  1.],
       [ 0.,  0.,  0.,  0.,  0.]])

これは、任意の2つのcsr_matricesをvstackするというより一般的なケースを処理する関数です。根本的なnumpy配列をコピーすることになりますが、それでもscipy vstackメソッドよりも大幅に高速です。

def csr_vappend(a,b):
    """ Takes in 2 csr_matrices and appends the second one to the bottom of the first one. 
    Much faster than scipy.sparse.vstack but assumes the type to be csr and overwrites
    the first matrix instead of copying it. The data, indices, and indptr still get copied."""

    a.data = np.hstack((a.data,b.data))
    a.indices = np.hstack((a.indices,b.indices))
    a.indptr = np.hstack((a.indptr,(b.indptr + a.nnz)[1:]))
    a._shape = (a.shape[0]+b.shape[0],b.shape[1])
    return a
26
JakeM

それでも解決策を探しているかどうかはわかりませんが、他の人がhstackvstackを調べている可能性があります- http://docs.scipy.org/doc/scipy/ reference/generated/scipy.sparse.hstack.html 。単一の追加行に対してcsr_matrixを定義してから、前の行列でvstackを定義できると思います。

8
Siddhant