[docs]defreduce(self,method,axis=(0,),keepdims=False,**kwargs):""" Performs a reduction operation on this array. Parameters ---------- method : numpy.ufunc The method to use for performing the reduction. axis : Union[int, Iterable[int]], optional The axes along which to perform the reduction. Uses all axes by default. keepdims : bool, optional Whether or not to keep the dimensions of the original array. kwargs : dict Any extra arguments to pass to the reduction operation. Returns ------- COO The result of the reduction operation. Raises ------ ValueError If reducing an all-zero axis would produce a nonzero result. Notes ----- This function internally calls :obj:`COO.sum_duplicates` to bring the array into canonical form. See Also -------- numpy.ufunc.reduce : A similar Numpy method. COO.nanreduce : Similar method with ``NaN`` skipping functionality. Examples -------- You can use the :obj:`COO.reduce` method to apply a reduction operation to any Numpy :code:`ufunc`. >>> x = np.ones((5, 5), dtype=np.int) >>> s = COO.from_numpy(x) >>> s2 = s.reduce(np.add, axis=1) >>> s2.todense() # doctest: +NORMALIZE_WHITESPACE array([5, 5, 5, 5, 5]) You can also use the :code:`keepdims` argument to keep the dimensions after the reduction. >>> s3 = s.reduce(np.add, axis=1, keepdims=True) >>> s3.shape (5, 1) You can also pass in any keyword argument that :obj:`numpy.ufunc.reduce` supports. For example, :code:`dtype`. Note that :code:`out` isn't supported. >>> s4 = s.reduce(np.add, axis=1, dtype=np.float16) >>> s4.dtype dtype('float16') By default, this reduces the array by only the first axis. >>> s.reduce(np.add) <COO: shape=(5,), dtype=int64, nnz=5, fill_value=0> """axis=normalize_axis(axis,self.ndim)zero_reduce_result=method.reduce([self.fill_value,self.fill_value],**kwargs)ifnotequivalent(zero_reduce_result,self.fill_value):raiseValueError("Performing this reduction operation would produce ""a dense result: %s"%str(method))ifaxisisNone:axis=tuple(range(self.ndim))ifnotisinstance(axis,tuple):axis=(axis,)axis=tuple(aifa>=0elsea+self.ndimforainaxis)ifset(axis)==set(range(self.ndim)):result=method.reduce(self.data,**kwargs)ifself.nnz!=self.size:result=method(result,self.fill_value,**kwargs)else:axis=tuple(axis)neg_axis=tuple(axforaxinrange(self.ndim)ifaxnotinset(axis))a=self.transpose(neg_axis+axis)a=a.reshape((np.prod([self.shape[d]fordinneg_axis]),np.prod([self.shape[d]fordinaxis])))result,inv_idx,counts=_grouped_reduce(a.data,a.coords[0],method,**kwargs)missing_counts=counts!=a.shape[1]result[missing_counts]=method(result[missing_counts],self.fill_value,**kwargs)coords=a.coords[0:1,inv_idx]# Filter out zerosmask=~equivalent(result,self.fill_value)coords=coords[:,mask]result=result[mask]a=COO(coords,result,shape=(a.shape[0],),has_duplicates=False,sorted=True,fill_value=self.fill_value)a=a.reshape(tuple(self.shape[d]fordinneg_axis))result=aifkeepdims:result=_keepdims(self,result,axis)returnresult

[docs]defsum(self,axis=None,keepdims=False,dtype=None,out=None):""" Performs a sum operation along the given axes. Uses all axes by default. Parameters ---------- axis : Union[int, Iterable[int]], optional The axes along which to sum. Uses all axes by default. keepdims : bool, optional Whether or not to keep the dimensions of the original array. dtype: numpy.dtype The data type of the output array. Returns ------- COO The reduced output sparse array. See Also -------- :obj:`numpy.sum` : Equivalent numpy function. scipy.sparse.coo_matrix.sum : Equivalent Scipy function. :obj:`nansum` : Function with ``NaN`` skipping. Notes ----- * This function internally calls :obj:`COO.sum_duplicates` to bring the array into canonical form. * The :code:`out` parameter is provided just for compatibility with Numpy and isn't actually supported. Examples -------- You can use :obj:`COO.sum` to sum an array across any dimension. >>> x = np.ones((5, 5), dtype=np.int) >>> s = COO.from_numpy(x) >>> s2 = s.sum(axis=1) >>> s2.todense() # doctest: +NORMALIZE_WHITESPACE array([5, 5, 5, 5, 5]) You can also use the :code:`keepdims` argument to keep the dimensions after the sum. >>> s3 = s.sum(axis=1, keepdims=True) >>> s3.shape (5, 1) You can pass in an output datatype, if needed. >>> s4 = s.sum(axis=1, dtype=np.float16) >>> s4.dtype dtype('float16') By default, this reduces the array down to one number, summing along all axes. >>> s.sum() 25 """returnnp.add.reduce(self,out=out,axis=axis,keepdims=keepdims,dtype=dtype)

[docs]defany(self,axis=None,keepdims=False,out=None):""" See if any values along array are ``True``. Uses all axes by default. Parameters ---------- axis : Union[int, Iterable[int]], optional The axes along which to minimize. Uses all axes by default. keepdims : bool, optional Whether or not to keep the dimensions of the original array. Returns ------- COO The reduced output sparse array. See Also -------- :obj:`numpy.all` : Equivalent numpy function. Notes ----- * This function internally calls :obj:`COO.sum_duplicates` to bring the array into canonical form. * The :code:`out` parameter is provided just for compatibility with Numpy and isn't actually supported. Examples -------- You can use :obj:`COO.min` to minimize an array across any dimension. >>> x = np.array([[False, False], ... [False, True ], ... [True, False], ... [True, True ]]) >>> s = COO.from_numpy(x) >>> s2 = s.any(axis=1) >>> s2.todense() # doctest: +SKIP array([False, True, True, True]) You can also use the :code:`keepdims` argument to keep the dimensions after the minimization. >>> s3 = s.any(axis=1, keepdims=True) >>> s3.shape (4, 1) By default, this reduces the array down to one number, minimizing along all axes. >>> s.any() True """returnnp.logical_or.reduce(self,out=out,axis=axis,keepdims=keepdims)

[docs]defall(self,axis=None,keepdims=False,out=None):""" See if all values in an array are ``True``. Uses all axes by default. Parameters ---------- axis : Union[int, Iterable[int]], optional The axes along which to minimize. Uses all axes by default. keepdims : bool, optional Whether or not to keep the dimensions of the original array. Returns ------- COO The reduced output sparse array. See Also -------- :obj:`numpy.all` : Equivalent numpy function. Notes ----- * This function internally calls :obj:`COO.sum_duplicates` to bring the array into canonical form. * The :code:`out` parameter is provided just for compatibility with Numpy and isn't actually supported. Examples -------- You can use :obj:`COO.min` to minimize an array across any dimension. >>> x = np.array([[False, False], ... [False, True ], ... [True, False], ... [True, True ]]) >>> s = COO.from_numpy(x) >>> s2 = s.all(axis=1) >>> s2.todense() # doctest: +SKIP array([False, False, False, True]) You can also use the :code:`keepdims` argument to keep the dimensions after the minimization. >>> s3 = s.all(axis=1, keepdims=True) >>> s3.shape (4, 1) By default, this reduces the array down to one boolean, minimizing along all axes. >>> s.all() False """returnnp.logical_and.reduce(self,out=out,axis=axis,keepdims=keepdims)

[docs]defto_scipy_sparse(self):""" Converts this :obj:`COO` object into a :obj:`scipy.sparse.coo_matrix`. Returns ------- :obj:`scipy.sparse.coo_matrix` The converted Scipy sparse matrix. Raises ------ ValueError If the array is not two-dimensional. ValueError If all the array doesn't zero fill-values. See Also -------- COO.tocsr : Convert to a :obj:`scipy.sparse.csr_matrix`. COO.tocsc : Convert to a :obj:`scipy.sparse.csc_matrix`. """check_zero_fill_value(self)ifself.ndim!=2:raiseValueError("Can only convert a 2-dimensional array to a Scipy sparse matrix.")result=scipy.sparse.coo_matrix((self.data,(self.coords[0],self.coords[1])),shape=self.shape)result.has_canonical_format=Truereturnresult

def_tocsr(self):ifself.ndim!=2:raiseValueError('This array must be two-dimensional for this conversion ''to work.')row,col=self.coords# Pass 3: count nonzeros in each rowindptr=np.zeros(self.shape[0]+1,dtype=np.int64)np.cumsum(np.bincount(row,minlength=self.shape[0]),out=indptr[1:])returnscipy.sparse.csr_matrix((self.data,col,indptr),shape=self.shape)

[docs]deftocsr(self):""" Converts this array to a :obj:`scipy.sparse.csr_matrix`. Returns ------- scipy.sparse.csr_matrix The result of the conversion. Raises ------ ValueError If the array is not two-dimensional. ValueError If all the array doesn't have zero fill-values. See Also -------- COO.tocsc : Convert to a :obj:`scipy.sparse.csc_matrix`. COO.to_scipy_sparse : Convert to a :obj:`scipy.sparse.coo_matrix`. scipy.sparse.coo_matrix.tocsr : Equivalent Scipy function. """check_zero_fill_value(self)ifself._cacheisnotNone:try:returnself._csrexceptAttributeError:passtry:self._csr=self._csc.tocsr()returnself._csrexceptAttributeError:passself._csr=csr=self._tocsr()else:csr=self._tocsr()returncsr

[docs]deftocsc(self):""" Converts this array to a :obj:`scipy.sparse.csc_matrix`. Returns ------- scipy.sparse.csc_matrix The result of the conversion. Raises ------ ValueError If the array is not two-dimensional. ValueError If the array doesn't have zero fill-values. See Also -------- COO.tocsr : Convert to a :obj:`scipy.sparse.csr_matrix`. COO.to_scipy_sparse : Convert to a :obj:`scipy.sparse.coo_matrix`. scipy.sparse.coo_matrix.tocsc : Equivalent Scipy function. """check_zero_fill_value(self)ifself._cacheisnotNone:try:returnself._cscexceptAttributeError:passtry:self._csc=self._csr.tocsc()returnself._cscexceptAttributeError:passself._csc=csc=self.tocsr().tocsc()else:csc=self.tocsr().tocsc()returncsc

[docs]defbroadcast_to(self,shape):""" Performs the equivalent of :obj:`numpy.broadcast_to` for :obj:`COO`. Note that this function returns a new array instead of a view. Parameters ---------- shape : tuple[int] The shape to broadcast the data to. Returns ------- COO The broadcasted sparse array. Raises ------ ValueError If the operand cannot be broadcast to the given shape. See also -------- :obj:`numpy.broadcast_to` : NumPy equivalent function """returnbroadcast_to(self,shape)

[docs]defround(self,decimals=0,out=None):""" Evenly round to the given number of decimals. See also -------- :obj:`numpy.round` : NumPy equivalent ufunc. :obj:`COO.elemwise`: Apply an arbitrary element-wise function to one or two arguments. Notes ----- The :code:`out` parameter is provided just for compatibility with Numpy and isn't actually supported. """ifoutisnotNoneandnotisinstance(out,tuple):out=(out,)returnself.__array_ufunc__(np.round,'__call__',self,decimals=decimals,out=out)

[docs]defastype(self,dtype):""" Copy of the array, cast to a specified type. See also -------- scipy.sparse.coo_matrix.astype : SciPy sparse equivalent function numpy.ndarray.astype : NumPy equivalent ufunc. :obj:`COO.elemwise`: Apply an arbitrary element-wise function to one or two arguments. Notes ----- The :code:`out` parameter is provided just for compatibility with Numpy and isn't actually supported. """returnself.__array_ufunc__(np.ndarray.astype,'__call__',self,dtype=dtype)

[docs]defasformat(self,format):""" Convert this sparse array to a given format. Parameters ---------- format : str A format string. Returns ------- out : SparseArray The converted array. Raises ------ NotImplementedError If the format isn't supported. """ifformat=='coo'orformatisCOO:returnselffrom..dokimportDOKifformat=='dok'orformatisDOK:returnDOK.from_coo(self)raiseNotImplementedError('The given format is not supported.')

[docs]defas_coo(x,shape=None,fill_value=None):""" Converts any given format to :obj:`COO`. See the "See Also" section for details. Parameters ---------- x : SparseArray or numpy.ndarray or scipy.sparse.spmatrix or Iterable. The item to convert. shape : tuple[int], optional The shape of the output array. Can only be used in case of Iterable. Returns ------- out : COO The converted :obj:`COO` array. See Also -------- SparseArray.asformat : A utility function to convert between formats in this library. COO.from_numpy : Convert a Numpy array to :obj:`COO`. COO.from_scipy_sparse : Convert a SciPy sparse matrix to :obj:`COO`. COO.from_iter : Convert an iterable to :obj:`COO`. """ifhasattr(x,'shape')andshapeisnotNone:raiseValueError('Cannot provide a shape in combination with something ''that already has a shape.')ifhasattr(x,'fill_value')andfill_valueisnotNone:raiseValueError('Cannot provide a fill-value in combination with something ''that already has a fill-value.')ifisinstance(x,SparseArray):returnx.asformat('coo')ifisinstance(x,np.ndarray):returnCOO.from_numpy(x,fill_value=fill_value)ifisinstance(x,scipy.sparse.spmatrix):returnCOO.from_scipy_sparse(x)ifisinstance(x,(Iterable,Iterator)):returnCOO.from_iter(x,shape=shape,fill_value=fill_value)raiseNotImplementedError('Format not supported for conversion. Supplied type is ''%s, see help(sparse.as_coo) for supported formats.'%type(x))

def_keepdims(original,new,axis):shape=list(original.shape)foraxinaxis:shape[ax]=1returnnew.reshape(shape)def_grouped_reduce(x,groups,method,**kwargs):""" Performs a :code:`ufunc` grouped reduce. Parameters ---------- x : np.ndarray The data to reduce. groups : np.ndarray The groups the data belongs to. The groups must be contiguous. method : np.ufunc The :code:`ufunc` to use to perform the reduction. kwargs : dict The kwargs to pass to the :code:`ufunc`'s :code:`reduceat` function. Returns ------- result : np.ndarray The result of the grouped reduce operation. inv_idx : np.ndarray The index of the first element where each group is found. counts : np.ndarray The number of elements in each group. """# Partial credit to @shoyer# Ref: https://gist.github.com/shoyer/f538ac78ae904c936844flag=np.concatenate(([True]iflen(x)!=0else[],groups[1:]!=groups[:-1]))inv_idx=np.flatnonzero(flag)result=method.reduceat(x,inv_idx,**kwargs)counts=np.diff(np.concatenate((inv_idx,[len(x)])))returnresult,inv_idx,counts