2016-08-04 6 views
0

私は2つの配列AとBを持っています。NumPyでは、AをBのインデックスとして使用できます。生成SciPy CSR Sparse Arraysを使用してある配列を別の配列にインデックスする方法は?

A = np.array([[1,2,3,1,7,3,1,2,3],[4,5,6,4,5,6,4,5,6],[7,8,9,7,8,9,7,8,9]]) 
B= np.array([1,2,3,4,5,6,7,8,9,0]) 
c = B[A] 

[[2 3 4 2 8 4 2 3 4] [5 6 7 5 6 7 5 6 7] [8 9 0 8 9 0 8 9 0]]

はしかし、私の場合、配列AとBは、scipyのダウンロードCSRスパース配列であり、彼らはインデックスをサポートしていないようです。

A_sparse = sparse.csr_matrix(A) 
B_sparse = sparse.csr_matrix(B) 
c = B_sparse[A_sparse] 

これは、その結果:アレイの上にループとを有する

def index_sparse(A,B):  
     A_sparse = scipy.sparse.coo_matrix(A) 
     B_sparse = sparse.csr_matrix(B) 
     res = sparse.csr_matrix(A_sparse) 
     for i,j,v in zip(A_sparse.row, A_sparse.col, A_sparse.data): 
      res[i,j] = B_sparse[0, v] 
     return res 

res = index_sparse(A, B) 
print res.todense() 

:スパース配列でnumpyのの行動を再現するには、以下の機能を私が作ってみた

IndexError: Indexing with sparse matrices is not supported except boolean indexing where matrix and index are equal shapes.

Pythonで新しい配列を作成するのは理想的ではありません。 SciPy/NumPyの組み込み関数を使ってこれを行うより良い方法はありますか?

答えて

1

スパースインデックスはあまり開発されていません。たとえば、coo形式は、それをまったく実装しません。

私はこの問題を実装しようとしていませんが、私は疎フォーマットの属性を扱う他の人に答えました。ですから、私はいくつかの一般的な観察をします。

B_sparseはマトリックスなので、その形状は(1,10)です。あなたの関数にしたよう

In [298]: B[None,:][:,A] 
Out[298]: 
array([[[2, 3, 4, 2, 8, 4, 2, 3, 4], 
     [5, 6, 7, 5, 6, 7, 5, 6, 7], 
     [8, 9, 0, 8, 9, 0, 8, 9, 0]]]) 

A_sparse.nonzero()のでB[A]に相当

In [294]: B_sparse[0,A] 
Out[294]: 
<3x9 sparse matrix of type '<class 'numpy.int32'>' 
    with 24 stored elements in Compressed Sparse Row format> 
In [295]: _.A 
Out[295]: 
array([[2, 3, 4, 2, 8, 4, 2, 3, 4], 
     [5, 6, 7, 5, 6, 7, 5, 6, 7], 
     [8, 9, 0, 8, 9, 0, 8, 9, 0]], dtype=int32) 

B_sparse[A,:]またはB_sparse[:,A]の行列バージョンを作成しようとしていることになるため、3D警告を与えていますA_sparse.tocoo()を返し、そのrowcolを返します。あなたがしているものと事実上同じです。私は十分にそれが堅牢であることを確認するためにそれをテストしていないのにここ

は、より速くなるべきものです:

In [342]: Ac=A_sparse.tocoo() 
In [343]: res=Ac.copy() 
In [344]: res.data[:]=B_sparse[0, Ac.data].A[0] 
In [345]: res 
Out[345]: 
<3x9 sparse matrix of type '<class 'numpy.int32'>' 
    with 27 stored elements in COOrdinate format> 
In [346]: res.A 
Out[346]: 
array([[2, 3, 4, 2, 8, 4, 2, 3, 4], 
     [5, 6, 7, 5, 6, 7, 5, 6, 7], 
     [8, 9, 0, 8, 9, 0, 8, 9, 0]], dtype=int32) 

この例では、クリーンアップができ2つのゼロが同様に存在している(res.nonzero()を見て)。

あなたはAc.rowAc.colからの値を持つ各res[i,j]を設定しているので、resAcと同じrow,col値を持っているので、私はコピーとしてそれを初期化します。その後、res.data属性を更新するだけです。 Bc.dataを直接索引するほうが速くなりますが、その希薄さは考慮されません。

関連する問題