Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.9/dist-packages/scipy/sparse/_coo.py: 15%
296 statements
« prev ^ index » next coverage.py v7.3.1, created at 2023-09-23 06:43 +0000
« prev ^ index » next coverage.py v7.3.1, created at 2023-09-23 06:43 +0000
1""" A sparse matrix in COOrdinate or 'triplet' format"""
3__docformat__ = "restructuredtext en"
5__all__ = ['coo_array', 'coo_matrix', 'isspmatrix_coo']
7from warnings import warn
9import numpy as np
11from ._matrix import spmatrix
12from ._sparsetools import coo_tocsr, coo_todense, coo_matvec
13from ._base import issparse, SparseEfficiencyWarning, _spbase, sparray
14from ._data import _data_matrix, _minmax_mixin
15from ._sputils import (upcast, upcast_char, to_native, isshape, getdtype,
16 getdata, downcast_intp_index,
17 check_shape, check_reshape_kwargs)
19import operator
22class _coo_base(_data_matrix, _minmax_mixin):
23 _format = 'coo'
25 def __init__(self, arg1, shape=None, dtype=None, copy=False):
26 _data_matrix.__init__(self)
28 if isinstance(arg1, tuple):
29 if isshape(arg1):
30 M, N = arg1
31 self._shape = check_shape((M, N))
32 idx_dtype = self._get_index_dtype(maxval=max(M, N))
33 data_dtype = getdtype(dtype, default=float)
34 self.row = np.array([], dtype=idx_dtype)
35 self.col = np.array([], dtype=idx_dtype)
36 self.data = np.array([], dtype=data_dtype)
37 self.has_canonical_format = True
38 else:
39 try:
40 obj, (row, col) = arg1
41 except (TypeError, ValueError) as e:
42 raise TypeError('invalid input format') from e
44 if shape is None:
45 if len(row) == 0 or len(col) == 0:
46 raise ValueError('cannot infer dimensions from zero '
47 'sized index arrays')
48 M = operator.index(np.max(row)) + 1
49 N = operator.index(np.max(col)) + 1
50 self._shape = check_shape((M, N))
51 else:
52 # Use 2 steps to ensure shape has length 2.
53 M, N = shape
54 self._shape = check_shape((M, N))
56 idx_dtype = self._get_index_dtype((row, col), maxval=max(self.shape), check_contents=True)
57 self.row = np.array(row, copy=copy, dtype=idx_dtype)
58 self.col = np.array(col, copy=copy, dtype=idx_dtype)
59 self.data = getdata(obj, copy=copy, dtype=dtype)
60 self.has_canonical_format = False
61 else:
62 if issparse(arg1):
63 if arg1.format == self.format and copy:
64 self.row = arg1.row.copy()
65 self.col = arg1.col.copy()
66 self.data = arg1.data.copy()
67 self._shape = check_shape(arg1.shape)
68 else:
69 coo = arg1.tocoo()
70 self.row = coo.row
71 self.col = coo.col
72 self.data = coo.data
73 self._shape = check_shape(coo.shape)
74 self.has_canonical_format = False
75 else:
76 #dense argument
77 M = np.atleast_2d(np.asarray(arg1))
79 if M.ndim != 2:
80 raise TypeError('expected dimension <= 2 array or matrix')
82 self._shape = check_shape(M.shape)
83 if shape is not None:
84 if check_shape(shape) != self._shape:
85 raise ValueError('inconsistent shapes: %s != %s' %
86 (shape, self._shape))
87 index_dtype = self._get_index_dtype(maxval=max(self._shape))
88 row, col = M.nonzero()
89 self.row = row.astype(index_dtype, copy=False)
90 self.col = col.astype(index_dtype, copy=False)
91 self.data = M[self.row, self.col]
92 self.has_canonical_format = True
94 if dtype is not None:
95 self.data = self.data.astype(dtype, copy=False)
97 self._check()
99 def reshape(self, *args, **kwargs):
100 shape = check_shape(args, self.shape)
101 order, copy = check_reshape_kwargs(kwargs)
103 # Return early if reshape is not required
104 if shape == self.shape:
105 if copy:
106 return self.copy()
107 else:
108 return self
110 nrows, ncols = self.shape
112 if order == 'C':
113 # Upcast to avoid overflows: the coo_array constructor
114 # below will downcast the results to a smaller dtype, if
115 # possible.
116 dtype = self._get_index_dtype(maxval=(ncols * max(0, nrows - 1) + max(0, ncols - 1)))
118 flat_indices = np.multiply(ncols, self.row, dtype=dtype) + self.col
119 new_row, new_col = divmod(flat_indices, shape[1])
120 elif order == 'F':
121 dtype = self._get_index_dtype(maxval=(nrows * max(0, ncols - 1) + max(0, nrows - 1)))
123 flat_indices = np.multiply(nrows, self.col, dtype=dtype) + self.row
124 new_col, new_row = divmod(flat_indices, shape[0])
125 else:
126 raise ValueError("'order' must be 'C' or 'F'")
128 # Handle copy here rather than passing on to the constructor so that no
129 # copy will be made of new_row and new_col regardless
130 if copy:
131 new_data = self.data.copy()
132 else:
133 new_data = self.data
135 return self.__class__((new_data, (new_row, new_col)),
136 shape=shape, copy=False)
138 reshape.__doc__ = _spbase.reshape.__doc__
140 def _getnnz(self, axis=None):
141 if axis is None:
142 nnz = len(self.data)
143 if nnz != len(self.row) or nnz != len(self.col):
144 raise ValueError('row, column, and data array must all be the '
145 'same length')
147 if self.data.ndim != 1 or self.row.ndim != 1 or \
148 self.col.ndim != 1:
149 raise ValueError('row, column, and data arrays must be 1-D')
151 return int(nnz)
153 if axis < 0:
154 axis += 2
155 if axis == 0:
156 return np.bincount(downcast_intp_index(self.col),
157 minlength=self.shape[1])
158 elif axis == 1:
159 return np.bincount(downcast_intp_index(self.row),
160 minlength=self.shape[0])
161 else:
162 raise ValueError('axis out of bounds')
164 _getnnz.__doc__ = _spbase._getnnz.__doc__
166 def _check(self):
167 """ Checks data structure for consistency """
169 # index arrays should have integer data types
170 if self.row.dtype.kind != 'i':
171 warn("row index array has non-integer dtype (%s) "
172 % self.row.dtype.name)
173 if self.col.dtype.kind != 'i':
174 warn("col index array has non-integer dtype (%s) "
175 % self.col.dtype.name)
177 idx_dtype = self._get_index_dtype((self.row, self.col), maxval=max(self.shape))
178 self.row = np.asarray(self.row, dtype=idx_dtype)
179 self.col = np.asarray(self.col, dtype=idx_dtype)
180 self.data = to_native(self.data)
182 if self.nnz > 0:
183 if self.row.max() >= self.shape[0]:
184 raise ValueError('row index exceeds matrix dimensions')
185 if self.col.max() >= self.shape[1]:
186 raise ValueError('column index exceeds matrix dimensions')
187 if self.row.min() < 0:
188 raise ValueError('negative row index found')
189 if self.col.min() < 0:
190 raise ValueError('negative column index found')
192 def transpose(self, axes=None, copy=False):
193 if axes is not None and axes != (1, 0):
194 raise ValueError("Sparse array/matrices do not support "
195 "an 'axes' parameter because swapping "
196 "dimensions is the only logical permutation.")
198 M, N = self.shape
199 return self.__class__((self.data, (self.col, self.row)),
200 shape=(N, M), copy=copy)
202 transpose.__doc__ = _spbase.transpose.__doc__
204 def resize(self, *shape):
205 shape = check_shape(shape)
206 new_M, new_N = shape
207 M, N = self.shape
209 if new_M < M or new_N < N:
210 mask = np.logical_and(self.row < new_M, self.col < new_N)
211 if not mask.all():
212 self.row = self.row[mask]
213 self.col = self.col[mask]
214 self.data = self.data[mask]
216 self._shape = shape
218 resize.__doc__ = _spbase.resize.__doc__
220 def toarray(self, order=None, out=None):
221 B = self._process_toarray_args(order, out)
222 fortran = int(B.flags.f_contiguous)
223 if not fortran and not B.flags.c_contiguous:
224 raise ValueError("Output array must be C or F contiguous")
225 M,N = self.shape
226 coo_todense(M, N, self.nnz, self.row, self.col, self.data,
227 B.ravel('A'), fortran)
228 return B
230 toarray.__doc__ = _spbase.toarray.__doc__
232 def tocsc(self, copy=False):
233 """Convert this array/matrix to Compressed Sparse Column format
235 Duplicate entries will be summed together.
237 Examples
238 --------
239 >>> from numpy import array
240 >>> from scipy.sparse import coo_array
241 >>> row = array([0, 0, 1, 3, 1, 0, 0])
242 >>> col = array([0, 2, 1, 3, 1, 0, 0])
243 >>> data = array([1, 1, 1, 1, 1, 1, 1])
244 >>> A = coo_array((data, (row, col)), shape=(4, 4)).tocsc()
245 >>> A.toarray()
246 array([[3, 0, 1, 0],
247 [0, 2, 0, 0],
248 [0, 0, 0, 0],
249 [0, 0, 0, 1]])
251 """
252 if self.nnz == 0:
253 return self._csc_container(self.shape, dtype=self.dtype)
254 else:
255 M,N = self.shape
256 idx_dtype = self._get_index_dtype(
257 (self.col, self.row), maxval=max(self.nnz, M)
258 )
259 row = self.row.astype(idx_dtype, copy=False)
260 col = self.col.astype(idx_dtype, copy=False)
262 indptr = np.empty(N + 1, dtype=idx_dtype)
263 indices = np.empty_like(row, dtype=idx_dtype)
264 data = np.empty_like(self.data, dtype=upcast(self.dtype))
266 coo_tocsr(N, M, self.nnz, col, row, self.data,
267 indptr, indices, data)
269 x = self._csc_container((data, indices, indptr), shape=self.shape)
270 if not self.has_canonical_format:
271 x.sum_duplicates()
272 return x
274 def tocsr(self, copy=False):
275 """Convert this array/matrix to Compressed Sparse Row format
277 Duplicate entries will be summed together.
279 Examples
280 --------
281 >>> from numpy import array
282 >>> from scipy.sparse import coo_array
283 >>> row = array([0, 0, 1, 3, 1, 0, 0])
284 >>> col = array([0, 2, 1, 3, 1, 0, 0])
285 >>> data = array([1, 1, 1, 1, 1, 1, 1])
286 >>> A = coo_array((data, (row, col)), shape=(4, 4)).tocsr()
287 >>> A.toarray()
288 array([[3, 0, 1, 0],
289 [0, 2, 0, 0],
290 [0, 0, 0, 0],
291 [0, 0, 0, 1]])
293 """
294 if self.nnz == 0:
295 return self._csr_container(self.shape, dtype=self.dtype)
296 else:
297 M,N = self.shape
298 idx_dtype = self._get_index_dtype(
299 (self.row, self.col), maxval=max(self.nnz, N)
300 )
301 row = self.row.astype(idx_dtype, copy=False)
302 col = self.col.astype(idx_dtype, copy=False)
304 indptr = np.empty(M + 1, dtype=idx_dtype)
305 indices = np.empty_like(col, dtype=idx_dtype)
306 data = np.empty_like(self.data, dtype=upcast(self.dtype))
308 coo_tocsr(M, N, self.nnz, row, col, self.data,
309 indptr, indices, data)
311 x = self._csr_container((data, indices, indptr), shape=self.shape)
312 if not self.has_canonical_format:
313 x.sum_duplicates()
314 return x
316 def tocoo(self, copy=False):
317 if copy:
318 return self.copy()
319 else:
320 return self
322 tocoo.__doc__ = _spbase.tocoo.__doc__
324 def todia(self, copy=False):
325 self.sum_duplicates()
326 ks = self.col - self.row # the diagonal for each nonzero
327 diags, diag_idx = np.unique(ks, return_inverse=True)
329 if len(diags) > 100:
330 # probably undesired, should todia() have a maxdiags parameter?
331 warn("Constructing a DIA matrix with %d diagonals "
332 "is inefficient" % len(diags), SparseEfficiencyWarning)
334 #initialize and fill in data array
335 if self.data.size == 0:
336 data = np.zeros((0, 0), dtype=self.dtype)
337 else:
338 data = np.zeros((len(diags), self.col.max()+1), dtype=self.dtype)
339 data[diag_idx, self.col] = self.data
341 return self._dia_container((data, diags), shape=self.shape)
343 todia.__doc__ = _spbase.todia.__doc__
345 def todok(self, copy=False):
346 self.sum_duplicates()
347 dok = self._dok_container((self.shape), dtype=self.dtype)
348 dok._update(zip(zip(self.row,self.col),self.data))
350 return dok
352 todok.__doc__ = _spbase.todok.__doc__
354 def diagonal(self, k=0):
355 rows, cols = self.shape
356 if k <= -rows or k >= cols:
357 return np.empty(0, dtype=self.data.dtype)
358 diag = np.zeros(min(rows + min(k, 0), cols - max(k, 0)),
359 dtype=self.dtype)
360 diag_mask = (self.row + k) == self.col
362 if self.has_canonical_format:
363 row = self.row[diag_mask]
364 data = self.data[diag_mask]
365 else:
366 row, _, data = self._sum_duplicates(self.row[diag_mask],
367 self.col[diag_mask],
368 self.data[diag_mask])
369 diag[row + min(k, 0)] = data
371 return diag
373 diagonal.__doc__ = _data_matrix.diagonal.__doc__
375 def _setdiag(self, values, k):
376 M, N = self.shape
377 if values.ndim and not len(values):
378 return
379 idx_dtype = self.row.dtype
381 # Determine which triples to keep and where to put the new ones.
382 full_keep = self.col - self.row != k
383 if k < 0:
384 max_index = min(M+k, N)
385 if values.ndim:
386 max_index = min(max_index, len(values))
387 keep = np.logical_or(full_keep, self.col >= max_index)
388 new_row = np.arange(-k, -k + max_index, dtype=idx_dtype)
389 new_col = np.arange(max_index, dtype=idx_dtype)
390 else:
391 max_index = min(M, N-k)
392 if values.ndim:
393 max_index = min(max_index, len(values))
394 keep = np.logical_or(full_keep, self.row >= max_index)
395 new_row = np.arange(max_index, dtype=idx_dtype)
396 new_col = np.arange(k, k + max_index, dtype=idx_dtype)
398 # Define the array of data consisting of the entries to be added.
399 if values.ndim:
400 new_data = values[:max_index]
401 else:
402 new_data = np.empty(max_index, dtype=self.dtype)
403 new_data[:] = values
405 # Update the internal structure.
406 self.row = np.concatenate((self.row[keep], new_row))
407 self.col = np.concatenate((self.col[keep], new_col))
408 self.data = np.concatenate((self.data[keep], new_data))
409 self.has_canonical_format = False
411 # needed by _data_matrix
412 def _with_data(self,data,copy=True):
413 """Returns a matrix with the same sparsity structure as self,
414 but with different data. By default the index arrays
415 (i.e. .row and .col) are copied.
416 """
417 if copy:
418 return self.__class__((data, (self.row.copy(), self.col.copy())),
419 shape=self.shape, dtype=data.dtype)
420 else:
421 return self.__class__((data, (self.row, self.col)),
422 shape=self.shape, dtype=data.dtype)
424 def sum_duplicates(self):
425 """Eliminate duplicate entries by adding them together
427 This is an *in place* operation
428 """
429 if self.has_canonical_format:
430 return
431 summed = self._sum_duplicates(self.row, self.col, self.data)
432 self.row, self.col, self.data = summed
433 self.has_canonical_format = True
435 def _sum_duplicates(self, row, col, data):
436 # Assumes (data, row, col) not in canonical format.
437 if len(data) == 0:
438 return row, col, data
439 # Sort indices w.r.t. rows, then cols. This corresponds to C-order,
440 # which we rely on for argmin/argmax to return the first index in the
441 # same way that numpy does (in the case of ties).
442 order = np.lexsort((col, row))
443 row = row[order]
444 col = col[order]
445 data = data[order]
446 unique_mask = ((row[1:] != row[:-1]) |
447 (col[1:] != col[:-1]))
448 unique_mask = np.append(True, unique_mask)
449 row = row[unique_mask]
450 col = col[unique_mask]
451 unique_inds, = np.nonzero(unique_mask)
452 data = np.add.reduceat(data, unique_inds, dtype=self.dtype)
453 return row, col, data
455 def eliminate_zeros(self):
456 """Remove zero entries from the array/matrix
458 This is an *in place* operation
459 """
460 mask = self.data != 0
461 self.data = self.data[mask]
462 self.row = self.row[mask]
463 self.col = self.col[mask]
465 #######################
466 # Arithmetic handlers #
467 #######################
469 def _add_dense(self, other):
470 if other.shape != self.shape:
471 raise ValueError('Incompatible shapes ({} and {})'
472 .format(self.shape, other.shape))
473 dtype = upcast_char(self.dtype.char, other.dtype.char)
474 result = np.array(other, dtype=dtype, copy=True)
475 fortran = int(result.flags.f_contiguous)
476 M, N = self.shape
477 coo_todense(M, N, self.nnz, self.row, self.col, self.data,
478 result.ravel('A'), fortran)
479 return self._container(result, copy=False)
481 def _mul_vector(self, other):
482 #output array
483 result = np.zeros(self.shape[0], dtype=upcast_char(self.dtype.char,
484 other.dtype.char))
485 coo_matvec(self.nnz, self.row, self.col, self.data, other, result)
486 return result
488 def _mul_multivector(self, other):
489 result = np.zeros((other.shape[1], self.shape[0]),
490 dtype=upcast_char(self.dtype.char, other.dtype.char))
491 for i, col in enumerate(other.T):
492 coo_matvec(self.nnz, self.row, self.col, self.data, col, result[i])
493 return result.T.view(type=type(other))
496def isspmatrix_coo(x):
497 """Is `x` of coo_matrix type?
499 Parameters
500 ----------
501 x
502 object to check for being a coo matrix
504 Returns
505 -------
506 bool
507 True if `x` is a coo matrix, False otherwise
509 Examples
510 --------
511 >>> from scipy.sparse import coo_array, coo_matrix, csr_matrix, isspmatrix_coo
512 >>> isspmatrix_coo(coo_matrix([[5]]))
513 True
514 >>> isspmatrix_coo(coo_array([[5]]))
515 False
516 >>> isspmatrix_coo(csr_matrix([[5]]))
517 False
518 """
519 return isinstance(x, coo_matrix)
522# This namespace class separates array from matrix with isinstance
523class coo_array(_coo_base, sparray):
524 """
525 A sparse array in COOrdinate format.
527 Also known as the 'ijv' or 'triplet' format.
529 This can be instantiated in several ways:
530 coo_array(D)
531 where D is a 2-D ndarray
533 coo_array(S)
534 with another sparse array or matrix S (equivalent to S.tocoo())
536 coo_array((M, N), [dtype])
537 to construct an empty array with shape (M, N)
538 dtype is optional, defaulting to dtype='d'.
540 coo_array((data, (i, j)), [shape=(M, N)])
541 to construct from three arrays:
542 1. data[:] the entries of the array, in any order
543 2. i[:] the row indices of the array entries
544 3. j[:] the column indices of the array entries
546 Where ``A[i[k], j[k]] = data[k]``. When shape is not
547 specified, it is inferred from the index arrays
549 Attributes
550 ----------
551 dtype : dtype
552 Data type of the array
553 shape : 2-tuple
554 Shape of the array
555 ndim : int
556 Number of dimensions (this is always 2)
557 nnz
558 size
559 data
560 COO format data array of the array
561 row
562 COO format row index array of the array
563 col
564 COO format column index array of the array
565 has_canonical_format : bool
566 Whether the matrix has sorted indices and no duplicates
567 format
568 T
570 Notes
571 -----
573 Sparse arrays can be used in arithmetic operations: they support
574 addition, subtraction, multiplication, division, and matrix power.
576 Advantages of the COO format
577 - facilitates fast conversion among sparse formats
578 - permits duplicate entries (see example)
579 - very fast conversion to and from CSR/CSC formats
581 Disadvantages of the COO format
582 - does not directly support:
583 + arithmetic operations
584 + slicing
586 Intended Usage
587 - COO is a fast format for constructing sparse arrays
588 - Once a COO array has been constructed, convert to CSR or
589 CSC format for fast arithmetic and matrix vector operations
590 - By default when converting to CSR or CSC format, duplicate (i,j)
591 entries will be summed together. This facilitates efficient
592 construction of finite element matrices and the like. (see example)
594 Canonical format
595 - Entries and indices sorted by row, then column.
596 - There are no duplicate entries (i.e. duplicate (i,j) locations)
597 - Data arrays MAY have explicit zeros.
599 Examples
600 --------
602 >>> # Constructing an empty array
603 >>> import numpy as np
604 >>> from scipy.sparse import coo_array
605 >>> coo_array((3, 4), dtype=np.int8).toarray()
606 array([[0, 0, 0, 0],
607 [0, 0, 0, 0],
608 [0, 0, 0, 0]], dtype=int8)
610 >>> # Constructing an array using ijv format
611 >>> row = np.array([0, 3, 1, 0])
612 >>> col = np.array([0, 3, 1, 2])
613 >>> data = np.array([4, 5, 7, 9])
614 >>> coo_array((data, (row, col)), shape=(4, 4)).toarray()
615 array([[4, 0, 9, 0],
616 [0, 7, 0, 0],
617 [0, 0, 0, 0],
618 [0, 0, 0, 5]])
620 >>> # Constructing an array with duplicate indices
621 >>> row = np.array([0, 0, 1, 3, 1, 0, 0])
622 >>> col = np.array([0, 2, 1, 3, 1, 0, 0])
623 >>> data = np.array([1, 1, 1, 1, 1, 1, 1])
624 >>> coo = coo_array((data, (row, col)), shape=(4, 4))
625 >>> # Duplicate indices are maintained until implicitly or explicitly summed
626 >>> np.max(coo.data)
627 1
628 >>> coo.toarray()
629 array([[3, 0, 1, 0],
630 [0, 2, 0, 0],
631 [0, 0, 0, 0],
632 [0, 0, 0, 1]])
634 """
637class coo_matrix(spmatrix, _coo_base):
638 """
639 A sparse matrix in COOrdinate format.
641 Also known as the 'ijv' or 'triplet' format.
643 This can be instantiated in several ways:
644 coo_matrix(D)
645 where D is a 2-D ndarray
647 coo_matrix(S)
648 with another sparse array or matrix S (equivalent to S.tocoo())
650 coo_matrix((M, N), [dtype])
651 to construct an empty matrix with shape (M, N)
652 dtype is optional, defaulting to dtype='d'.
654 coo_matrix((data, (i, j)), [shape=(M, N)])
655 to construct from three arrays:
656 1. data[:] the entries of the matrix, in any order
657 2. i[:] the row indices of the matrix entries
658 3. j[:] the column indices of the matrix entries
660 Where ``A[i[k], j[k]] = data[k]``. When shape is not
661 specified, it is inferred from the index arrays
663 Attributes
664 ----------
665 dtype : dtype
666 Data type of the matrix
667 shape : 2-tuple
668 Shape of the matrix
669 ndim : int
670 Number of dimensions (this is always 2)
671 nnz
672 size
673 data
674 COO format data array of the matrix
675 row
676 COO format row index array of the matrix
677 col
678 COO format column index array of the matrix
679 has_canonical_format : bool
680 Whether the matrix has sorted indices and no duplicates
681 format
682 T
684 Notes
685 -----
687 Sparse matrices can be used in arithmetic operations: they support
688 addition, subtraction, multiplication, division, and matrix power.
690 Advantages of the COO format
691 - facilitates fast conversion among sparse formats
692 - permits duplicate entries (see example)
693 - very fast conversion to and from CSR/CSC formats
695 Disadvantages of the COO format
696 - does not directly support:
697 + arithmetic operations
698 + slicing
700 Intended Usage
701 - COO is a fast format for constructing sparse matrices
702 - Once a COO matrix has been constructed, convert to CSR or
703 CSC format for fast arithmetic and matrix vector operations
704 - By default when converting to CSR or CSC format, duplicate (i,j)
705 entries will be summed together. This facilitates efficient
706 construction of finite element matrices and the like. (see example)
708 Canonical format
709 - Entries and indices sorted by row, then column.
710 - There are no duplicate entries (i.e. duplicate (i,j) locations)
711 - Data arrays MAY have explicit zeros.
713 Examples
714 --------
716 >>> # Constructing an empty matrix
717 >>> import numpy as np
718 >>> from scipy.sparse import coo_matrix
719 >>> coo_matrix((3, 4), dtype=np.int8).toarray()
720 array([[0, 0, 0, 0],
721 [0, 0, 0, 0],
722 [0, 0, 0, 0]], dtype=int8)
724 >>> # Constructing a matrix using ijv format
725 >>> row = np.array([0, 3, 1, 0])
726 >>> col = np.array([0, 3, 1, 2])
727 >>> data = np.array([4, 5, 7, 9])
728 >>> coo_matrix((data, (row, col)), shape=(4, 4)).toarray()
729 array([[4, 0, 9, 0],
730 [0, 7, 0, 0],
731 [0, 0, 0, 0],
732 [0, 0, 0, 5]])
734 >>> # Constructing a matrix with duplicate indices
735 >>> row = np.array([0, 0, 1, 3, 1, 0, 0])
736 >>> col = np.array([0, 2, 1, 3, 1, 0, 0])
737 >>> data = np.array([1, 1, 1, 1, 1, 1, 1])
738 >>> coo = coo_matrix((data, (row, col)), shape=(4, 4))
739 >>> # Duplicate indices are maintained until implicitly or explicitly summed
740 >>> np.max(coo.data)
741 1
742 >>> coo.toarray()
743 array([[3, 0, 1, 0],
744 [0, 2, 0, 0],
745 [0, 0, 0, 0],
746 [0, 0, 0, 1]])
748 """