2012-06-20 4 views
20

PyTablesでnumpyのcsr_matrixを保存するのに問題があります。私はこのエラーを取得しています:HDF5(PyTables)にnumpyの疎な行列を保存する

TypeError: objects of type ``csr_matrix`` are not supported in this context, sorry; supported objects are: NumPy array, record or scalar; homogeneous list or tuple, integer, float, complex or string 

マイコード:

f = tables.openFile(path,'w') 

atom = tables.Atom.from_dtype(self.count_vector.dtype) 
ds = f.createCArray(f.root, 'count', atom, self.count_vector.shape) 
ds[:] = self.count_vector 
f.close() 

任意のアイデア?

おかげ

+0

ディスク上のデータのサイズが心配ですか?私はhdf5ファイルを圧縮形式で保存することができます。その場合、密度の高い行列を保存するだけで済むかもしれません。 – user545424

+2

http://stackoverflow.com/questions/8895120/using-pytables-which-is-more-efficient-scipy-sparse-or-numpy-dense-matrixを参照してください。スパース行列のpytablesサポートがないようです。 – user545424

答えて

21

CSRマトリックスは、そのdataindicesindptr属性から完全に再構成することができます。これらは単に普通の配列なので、pytablesに3つの別々の配列として格納してから、csr_matrixのコンストラクタに戻しても問題ありません。 scipy docsを参照してください。

編集:最後の列場合:ピエトロの答えはshapeメンバーもDavePによって答えはほとんど権利である...しかし、非常にスパース行列のための問題を引き起こす可能性があります

+0

しかし、私はこの点を高密度マトリックスのように使うことを考えています。 csr_matrixを "dense-format" pytablesインスタンスに変換するにはどうすればよいですか? – Will

+0

メンバー関数toarrayを使用してcsr_matrixを高密度配列に変換することができます。これをpytablesに保存することができます。もちろん、hdf5にはファイル圧縮オプションがありますが、多くのファイルスペースを無駄にする可能性があります。 – DaveP

+1

NumPyのtoarray()は、巨大なものから密なものへの変換を扱うことができません。私はCSRから直接テーブルを構築したいと考えていました。 – Will

33

を保存する必要があることを指摘しています行または列が空の場合、それらは削除されます。したがって、すべてが機能することを確認するには、「シェイプ」属性も格納する必要があります。

これは私が定期的に使用するコードです:

import tables as tb 
from numpy import array 
from scipy import sparse 

def store_sparse_mat(m, name, store='store.h5'): 
    msg = "This code only works for csr matrices" 
    assert(m.__class__ == sparse.csr.csr_matrix), msg 
    with tb.openFile(store,'a') as f: 
     for par in ('data', 'indices', 'indptr', 'shape'): 
      full_name = '%s_%s' % (name, par) 
      try: 
       n = getattr(f.root, full_name) 
       n._f_remove() 
      except AttributeError: 
       pass 

      arr = array(getattr(m, par)) 
      atom = tb.Atom.from_dtype(arr.dtype) 
      ds = f.createCArray(f.root, full_name, atom, arr.shape) 
      ds[:] = arr 

def load_sparse_mat(name, store='store.h5'): 
    with tb.openFile(store) as f: 
     pars = [] 
     for par in ('data', 'indices', 'indptr', 'shape'): 
      pars.append(getattr(f.root, '%s_%s' % (name, par)).read()) 
    m = sparse.csr_matrix(tuple(pars[:3]), shape=pars[3]) 
    return m 

CSC行列に適合するように簡単です。

+0

上記の答えで 'name'変数は何に対応していますか? – Rama

+1

@Rama:オブジェクトを格納するためのキーです。任意に、それを取り戻すために必要なのは(同じHDFストア内に、たくさんの異なるオブジェクトを格納することができます)。 –

6

Python 3.6とPyTables 3.xに対して、PyTablesの関数名が2.xからのアップグレードで変更されたため、私はPietro Battistonの優れた答えを更新しました。

import numpy as np 
from scipy import sparse 
import tables 

def store_sparse_mat(M, name, filename='store.h5'): 
    """ 
    Store a csr matrix in HDF5 

    Parameters 
    ---------- 
    M : scipy.sparse.csr.csr_matrix 
     sparse matrix to be stored 

    name: str 
     node prefix in HDF5 hierarchy 

    filename: str 
     HDF5 filename 
    """ 
    assert(M.__class__ == sparse.csr.csr_matrix), 'M must be a csr matrix' 
    with tables.open_file(filename, 'a') as f: 
     for attribute in ('data', 'indices', 'indptr', 'shape'): 
      full_name = f'{name}_{attribute}' 

      # remove existing nodes 
      try: 
       n = getattr(f.root, full_name) 
       n._f_remove() 
      except AttributeError: 
       pass 

      # add nodes 
      arr = np.array(getattr(M, attribute)) 
      atom = tables.Atom.from_dtype(arr.dtype) 
      ds = f.create_carray(f.root, full_name, atom, arr.shape) 
      ds[:] = arr 

def load_sparse_mat(name, filename='store.h5'): 
    """ 
    Load a csr matrix from HDF5 

    Parameters 
    ---------- 
    name: str 
     node prefix in HDF5 hierarchy 

    filename: str 
     HDF5 filename 

    Returns 
    ---------- 
    M : scipy.sparse.csr.csr_matrix 
     loaded sparse matrix 
    """ 
    with tables.open_file(filename) as f: 

     # get nodes 
     attributes = [] 
     for attribute in ('data', 'indices', 'indptr', 'shape'): 
      attributes.append(getattr(f.root, f'{name}_{attribute}').read()) 

    # construct sparse matrix 
    M = sparse.csr_matrix(tuple(attributes[:3]), shape=attributes[3]) 
    return M 
関連する問題