# -*- coding: utf-8 -*from.importArrayProxyclassSparseMatrixProxy(ArrayProxy):"""Provides a dictionary-based interface from database row ids to array indices for sparse matrices. Does not assume a certain sparsity structure. """def__init__(self,data,row_dict,col_dict,*args,**kwargs):self.row_dict=row_dictself.col_dict=col_dictself.data=datatry:self.format=self.data.getformat()exceptAttributeError:raiseTypeError("Must pass a Scipy sparse matrix")def__getitem__(self,*args):assertlen(args)==1x=self.translate(args[0][0],"row")y=self.translate(args[0][1],"col")ifx==slice(None)ory==slice(None):raiseNotImplementedError("SparseMatrixProxy doesn't support ""slices; use CompressedSparseMatrixProxy for slices")returnself.data.__getitem__((x,y),)def__setitem__(self,*args):assertlen(args)==2x=self.translate(args[0][0],"row")y=self.translate(args[0][1],"col")ifx==slice(None)ory==slice(None):raiseNotImplementedError("SparseMatrixProxy doesn't support ""assignment by slice")self.data.__setitem__((x,y),args[1])defget_row_as_dict(self,row):raiseNotImplementedError("Use CompressedSparseMatrixProxy for ""dictionary matrix slices")defget_col_as_dict(self,col):raiseNotImplementedError("Use CompressedSparseMatrixProxy for ""dictionary matrix slices")deftoarray(self):returnself.data.toarray()deftodense(self):returnself.data.todense()@propertydefnnz(self):# Used to use getnzmax, but that seems to be missing from newest scipyreturnself.data.getnnz()classCompressedSparseMatrixProxy(SparseMatrixProxy):"""Subclass of SparseMatrixProxy for CSR (comma separated row) or CSC (comma separated column) matrices.This class will create, on demand, the complementary matrix type (e.g. CSC for CSR) for efficient slicing and multiple assignment. If a matrix is changed, a *dirty* flag is set that tells the class to re-create the complementary matrix before accessing its information. All updates to complementary matrices are lazy. """__slots__=['row_dict','col_dict','format','dirty','_csr','_csc']def__init__(self,data,row_dict,col_dict,*args,**kwargs):self.row_dict=row_dictself.col_dict=col_dictself.dirty=True# try:self.format=data.getformat()ifself.format=="csc":self._csc=dataelse:self._csr=data.tocsr()self.format="csr"def__getitem__(self,*args):assertlen(args)==1x=self.translate(args[0][0],"row")y=self.translate(args[0][1],"col")ifisinstance(x,slice)andisinstance(y,slice):raiseNotImplementedError("Convert to dense matrix to do slices on multiple dimensions")elifisinstance(x,slice):ifself.dirtyandself.format=="csr":self._csc=self._csr.tocsc()returnself._csc.__getitem__((x,y),)elifisinstance(y,slice):ifself.dirtyandself.format=="csc":self._csr=self._csc.tocsr()returnself._csr.__getitem__((x,y),)else:returnself.data.__getitem__((x,y),)def_get_data(self):ifself.format=="csr":returnself._csrelse:returnself._cscdef_set_data(self,data):self.dirty=Trueifself.format=="csr":self._csr=dataelse:self._csc=datadata=property(_get_data,_set_data)def__setitem__(self,*args):# Set dirty flag to indicate that matrix has changed, and need to# recompute the partner matrix if is accessedself.dirty=True# TODO: Warn if setting slicing on compressed sparse matrix?super(CompressedSparseMatrixProxy,self).__setitem__(*args)defget_row_as_dict(self,row):obj=self.__getitem__((row,slice(None)),)returndict([(self.row_dict_rev[obj.indices[index]],obj.data[index])forindexinxrange(obj.indices.shape[0])])defget_col_as_dict(self,col):obj=self.__getitem__((slice(None),col),)returndict([(self.col_dict_rev[obj.indices[index]],obj.data[index])forindexinxrange(obj.indices.shape[0])])