Coverage for /usr/lib/python3/dist-packages/scipy/sparse/_csc.py: 39%
90 statements
« prev ^ index » next coverage.py v7.9.1, created at 2025-06-14 15:55 +0200
« prev ^ index » next coverage.py v7.9.1, created at 2025-06-14 15:55 +0200
1"""Compressed Sparse Column matrix format"""
2__docformat__ = "restructuredtext en"
4__all__ = ['csc_array', 'csc_matrix', 'isspmatrix_csc']
7import numpy as np
9from ._matrix import spmatrix, _array_doc_to_matrix
10from ._base import _spbase, sparray
11from ._sparsetools import csc_tocsr, expandptr
12from ._sputils import upcast
14from ._compressed import _cs_matrix
17class _csc_base(_cs_matrix):
18 """
19 Compressed Sparse Column matrix
21 This can be instantiated in several ways:
23 csc_array(D)
24 with a dense matrix or rank-2 ndarray D
26 csc_array(S)
27 with another sparse matrix S (equivalent to S.tocsc())
29 csc_array((M, N), [dtype])
30 to construct an empty matrix with shape (M, N)
31 dtype is optional, defaulting to dtype='d'.
33 csc_array((data, (row_ind, col_ind)), [shape=(M, N)])
34 where ``data``, ``row_ind`` and ``col_ind`` satisfy the
35 relationship ``a[row_ind[k], col_ind[k]] = data[k]``.
37 csc_array((data, indices, indptr), [shape=(M, N)])
38 is the standard CSC representation where the row indices for
39 column i are stored in ``indices[indptr[i]:indptr[i+1]]``
40 and their corresponding values are stored in
41 ``data[indptr[i]:indptr[i+1]]``. If the shape parameter is
42 not supplied, the matrix dimensions are inferred from
43 the index arrays.
45 Attributes
46 ----------
47 dtype : dtype
48 Data type of the matrix
49 shape : 2-tuple
50 Shape of the matrix
51 ndim : int
52 Number of dimensions (this is always 2)
53 nnz
54 Number of stored values, including explicit zeros
55 data
56 Data array of the matrix
57 indices
58 CSC format index array
59 indptr
60 CSC format index pointer array
61 has_sorted_indices
62 Whether indices are sorted
64 Notes
65 -----
67 Sparse matrices can be used in arithmetic operations: they support
68 addition, subtraction, multiplication, division, and matrix power.
70 Advantages of the CSC format
71 - efficient arithmetic operations CSC + CSC, CSC * CSC, etc.
72 - efficient column slicing
73 - fast matrix vector products (CSR, BSR may be faster)
75 Disadvantages of the CSC format
76 - slow row slicing operations (consider CSR)
77 - changes to the sparsity structure are expensive (consider LIL or DOK)
79 Canonical format
80 - Within each column, indices are sorted by row.
81 - There are no duplicate entries.
83 Examples
84 --------
86 >>> import numpy as np
87 >>> from scipy.sparse import csc_array
88 >>> csc_array((3, 4), dtype=np.int8).toarray()
89 array([[0, 0, 0, 0],
90 [0, 0, 0, 0],
91 [0, 0, 0, 0]], dtype=int8)
93 >>> row = np.array([0, 2, 2, 0, 1, 2])
94 >>> col = np.array([0, 0, 1, 2, 2, 2])
95 >>> data = np.array([1, 2, 3, 4, 5, 6])
96 >>> csc_array((data, (row, col)), shape=(3, 3)).toarray()
97 array([[1, 0, 4],
98 [0, 0, 5],
99 [2, 3, 6]])
101 >>> indptr = np.array([0, 2, 3, 6])
102 >>> indices = np.array([0, 2, 2, 0, 1, 2])
103 >>> data = np.array([1, 2, 3, 4, 5, 6])
104 >>> csc_array((data, indices, indptr), shape=(3, 3)).toarray()
105 array([[1, 0, 4],
106 [0, 0, 5],
107 [2, 3, 6]])
109 """
110 _format = 'csc'
112 def transpose(self, axes=None, copy=False):
113 if axes is not None:
114 raise ValueError("Sparse matrices do not support "
115 "an 'axes' parameter because swapping "
116 "dimensions is the only logical permutation.")
118 M, N = self.shape
120 return self._csr_container((self.data, self.indices,
121 self.indptr), (N, M), copy=copy)
123 transpose.__doc__ = _spbase.transpose.__doc__
125 def __iter__(self):
126 yield from self.tocsr()
128 def tocsc(self, copy=False):
129 if copy:
130 return self.copy()
131 else:
132 return self
134 tocsc.__doc__ = _spbase.tocsc.__doc__
136 def tocsr(self, copy=False):
137 M,N = self.shape
138 idx_dtype = self._get_index_dtype((self.indptr, self.indices),
139 maxval=max(self.nnz, N))
140 indptr = np.empty(M + 1, dtype=idx_dtype)
141 indices = np.empty(self.nnz, dtype=idx_dtype)
142 data = np.empty(self.nnz, dtype=upcast(self.dtype))
144 csc_tocsr(M, N,
145 self.indptr.astype(idx_dtype),
146 self.indices.astype(idx_dtype),
147 self.data,
148 indptr,
149 indices,
150 data)
152 A = self._csr_container(
153 (data, indices, indptr),
154 shape=self.shape, copy=False
155 )
156 A.has_sorted_indices = True
157 return A
159 tocsr.__doc__ = _spbase.tocsr.__doc__
161 def nonzero(self):
162 # CSC can't use _cs_matrix's .nonzero method because it
163 # returns the indices sorted for self transposed.
165 # Get row and col indices, from _cs_matrix.tocoo
166 major_dim, minor_dim = self._swap(self.shape)
167 minor_indices = self.indices
168 major_indices = np.empty(len(minor_indices), dtype=self.indices.dtype)
169 expandptr(major_dim, self.indptr, major_indices)
170 row, col = self._swap((major_indices, minor_indices))
172 # Remove explicit zeros
173 nz_mask = self.data != 0
174 row = row[nz_mask]
175 col = col[nz_mask]
177 # Sort them to be in C-style order
178 ind = np.argsort(row, kind='mergesort')
179 row = row[ind]
180 col = col[ind]
182 return row, col
184 nonzero.__doc__ = _cs_matrix.nonzero.__doc__
186 def _getrow(self, i):
187 """Returns a copy of row i of the matrix, as a (1 x n)
188 CSR matrix (row vector).
189 """
190 M, N = self.shape
191 i = int(i)
192 if i < 0:
193 i += M
194 if i < 0 or i >= M:
195 raise IndexError('index (%d) out of range' % i)
196 return self._get_submatrix(minor=i).tocsr()
198 def _getcol(self, i):
199 """Returns a copy of column i of the matrix, as a (m x 1)
200 CSC matrix (column vector).
201 """
202 M, N = self.shape
203 i = int(i)
204 if i < 0:
205 i += N
206 if i < 0 or i >= N:
207 raise IndexError('index (%d) out of range' % i)
208 return self._get_submatrix(major=i, copy=True)
210 def _get_intXarray(self, row, col):
211 return self._major_index_fancy(col)._get_submatrix(minor=row)
213 def _get_intXslice(self, row, col):
214 if col.step in (1, None):
215 return self._get_submatrix(major=col, minor=row, copy=True)
216 return self._major_slice(col)._get_submatrix(minor=row)
218 def _get_sliceXint(self, row, col):
219 if row.step in (1, None):
220 return self._get_submatrix(major=col, minor=row, copy=True)
221 return self._get_submatrix(major=col)._minor_slice(row)
223 def _get_sliceXarray(self, row, col):
224 return self._major_index_fancy(col)._minor_slice(row)
226 def _get_arrayXint(self, row, col):
227 return self._get_submatrix(major=col)._minor_index_fancy(row)
229 def _get_arrayXslice(self, row, col):
230 return self._major_slice(col)._minor_index_fancy(row)
232 # these functions are used by the parent class (_cs_matrix)
233 # to remove redudancy between csc_array and csr_matrix
234 def _swap(self, x):
235 """swap the members of x if this is a column-oriented matrix
236 """
237 return x[1], x[0]
240def isspmatrix_csc(x):
241 """Is `x` of csc_matrix type?
243 Parameters
244 ----------
245 x
246 object to check for being a csc matrix
248 Returns
249 -------
250 bool
251 True if `x` is a csc matrix, False otherwise
253 Examples
254 --------
255 >>> from scipy.sparse import csc_array, csc_matrix, coo_matrix, isspmatrix_csc
256 >>> isspmatrix_csc(csc_matrix([[5]]))
257 True
258 >>> isspmatrix_csc(csc_array([[5]]))
259 False
260 >>> isspmatrix_csc(coo_matrix([[5]]))
261 False
262 """
263 return isinstance(x, csc_matrix)
266# This namespace class separates array from matrix with isinstance
267class csc_array(_csc_base, sparray):
268 pass
270csc_array.__doc__ = _csc_base.__doc__
272class csc_matrix(spmatrix, _csc_base):
273 pass
275csc_matrix.__doc__ = _array_doc_to_matrix(_csc_base.__doc__)