2011-01-14 10 views
26

Sanırım bir NxN matrisini M (lil_matrix veya csr_matrix) scipy.sparse'den aldım ve bunu yapmak istiyorum (N + 1) xN burada M_modified [i, j] = 0 j) < = < N (ve tüm j) ve M için [N, j] = 0, tüm j için. Temel olarak, M'nin altına bir sıfir sırasını eklemek ve matrisin kalanını korumak istiyorum. Verileri kopyalamadan bunu yapmanın bir yolu var mı?genişleyen (bir satır veya sütun ekleyerek) bir scipy.sparse matrisi

cevap

4

Kopyalama işleminden gerçekten kurtulmanın bir yolu olduğunu sanmıyorum. Her iki seyrek matris türü, verilerini içsel olarak Numpy dizileri (csr'nin veri ve dizin özniteliklerinde ve veri ve satır özniteliklerinde) olarak depolar ve Numpy dizileri genişletilemez. Daha fazla bilgi ile

Güncelleme:

LIL bağlantılı liste anlama geliyor, ama şu anki uygulama oldukça adına yaşamak değildir. data ve rows için kullanılan Numpy dizileri her ikisi de yazım nesnesidir. Bu dizilerdeki nesnelerin her biri aslında Python listeleridir (tüm değerler bir satırda sıfır olduğunda boş bir liste). Python listeleri tam olarak bağlantılı listeler değildir, fakat onlar O (1) look-up nedeniyle yakın ve oldukça açık bir şekilde daha iyi bir seçimdir. Şahsen, sadece bir Python listesi yerine bir Numpy dizisi nesnesi kullanmanın noktasını hemen göremiyorum. Python listelerini kullanmak için mevcut lil uygulamasını oldukça kolay bir şekilde değiştirebilirsiniz, bunun yerine tüm matrisi kopyalamadan bir satır eklemenizi sağlar.

+0

, sen kaputun altında daha kolay uzatılabilir veri türünü kullanan scipy.sparse arayüzü ile yeni bir sınıf uygulamak mümkün olabilir. –

+1

Belki de temel veri yapısı hakkında daha fazla bilgi sahibi olan biri buna cevap verebilir. Lil_matrix'in bağlantılı listelerle uygulandığını düşündüm. – RandomGuy

+0

@scandido, en son eklememin sorunuza cevap verip vermediğine bakın. –

8

Hala bir çözüm arıyorsanız emin olabilirsiniz, ancak diğerleri hstack ve vstack - http://docs.scipy.org/doc/scipy/reference/generated/scipy.sparse.hstack.html - http://docs.scipy.org/doc/scipy/reference/generated/scipy.sparse.hstack.html. Tek bir ek satır için bir csr_matrix ve daha önceki matrisle vstack tanımlayabiliriz.

+0

[vstack için kaynak kodu] (https://github.com/scipy/scipy/blob/v0.19.0/scipy/sparse/construct.py#L461-L492) Bunun anlamı, girişin yeni bir kopyasını döndürür Matrisler, bu yüzden bir matris ** inplace ** genişletmek istiyorsak yeterince verimli değil. – JenkinsY

24

Scipy'nin verileri kopyalamadan bunu yapmanın bir yolu yoktur, ancak seyrek matrisi tanımlayan özellikleri değiştirerek bunu kendiniz yapabilirsiniz.

csr_matrix oluşturan 4 özellikleri vardır:

veriler: matris

endeksleri olarak gerçek değerleri içeren bir dizi: veri her değere tekabül eden sütun indeksi içeren bir dizi

indptr: Her satır için verilerdeki ilk değerden önceki dizini belirten bir dizi. Satır boşsa, dizin önceki sütundakiyle aynıdır.

şekli: matrisin sadece yapmanız gereken tek şey matris için şekil ve indptr değiştirmektir altına sıfır bir sıra ekliyorsanız

şeklini içeren bir tanımlama grubu.

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.]]) 

Herhangi bir 2 csr_matrices'i vurarak daha genel bir durumun ele alınacağı bir işlev. Hala alttaki numpy dizilerini kopyalamakla bitiyorsunuz ama yine de scipy vstack yönteminden çok daha hızlı. uygulamanızda yeterli kritik ise

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 
+1

"a" işlevini bile döndürmeyerek uzaklaşabileceğinizi düşünüyorum, çünkü işlev argümanları referans olarak geçtiğinden "a" işlevi işlev kapsamı içinde bile doğrudan değiştirilir. Ayrıca, bir csc_happend (a, b) analog olabilir mi? – richizy

+0

Sadece şekli sıfırlamak için iyi bir fikir. – Jan

İlgili konular