Migration von spmatrix zu sparray#

Dieses Dokument bietet Anleitungen zur Konvertierung von Code von sparse Matrizen zu sparse Arrays in scipy.sparse.

Die Änderung von sparse Matrizen zu sparse Arrays spiegelt die Konvertierung von np.matrix zu np.ndarray wider. Im Wesentlichen müssen wir von einem ausschließlich auf 2D-Matrixmultiplikation zentrierten matrix-Objekt zu einem 1D- oder 2D-"Array"-Objekt wechseln, das den Matrixmultiplikationsoperator und elementweise Berechnungen unterstützt.

Notation: Für diese Anleitung bezeichnen wir die sparse Array-Klassen allgemein als sparray und die sparse Matrix-Klassen als spmatrix. Dichte NumPy-Arrays werden als np.ndarray und dichte Matrixklassen als np.matrix bezeichnet. Unterstützte sparse Formate werden als BSR, COO, CSC, CSR, DIA, DOK, LIL bezeichnet und alle Formate werden sowohl von sparray als auch von spmatrix unterstützt. Der Begriff sparse bezieht sich auf entweder sparray oder spmatrix, während dense sich auf entweder np.ndarray oder np.matrix bezieht.

Überblick und Gesamtbild#

  • Die Konstruktor-Namen *_matrix, z.B. csr_matrix, werden in *_array geändert.

  • Eine spmatrix M ist immer 2D (Zeilen x Spalten), selbst bei z.B. M.min(axis=0). Eine sparray A kann 1D oder 2D sein. NumPy-Skalare werden für vollständige (0D) Reduktionen zurückgegeben, d.h. M.min().

  • Das Iterieren über ein sparray ergibt 1D-sparrays. Das Iterieren über spmatrix ergibt 2D-sparse Matrizen.

  • Operatoren, die ihr Verhalten ändern, sind: *, @, *=, @=, **

    • Skalare Multiplikation, z.B. 5 * A, verwendet *, und 5 @ A ist nicht implementiert.

    • sparrays verwenden * für elementweise Multiplikation und @ für Matrixmultiplikation, während spmatrices entweder den Operator * oder @ für Matrixmultiplikation verwenden. Beide können A.multiply(B) für elementweise Multiplikation verwenden.

    • Skalare Exponenten, z.B. A**2, verwenden elementweise Potenz für sparray und Matrixpotenz für spmatrix. Matrixpotenz für sparrays verwendet scipy.sparse.linalg.matrix_power(A, n).

  • Wenn Index-Arrays an die Konstruktorfunktionen übergeben werden, wählt spmatrix einen dtype basierend auf dem dtype und den Werten der eingehenden Arrays aus, während sparray nur den dtype der eingehenden Arrays berücksichtigt. Zum Beispiel ergibt M=csr_matrix((data, indices, indptr)) einen int32 dtype für M.indices, solange die Werte in indices und indptr klein sind, auch wenn der dtype der eingehenden Arrays int64 ist. Im Gegensatz dazu ergibt A=csr_array((data, indices, indptr)) einen int64 dtype für A.indices, wenn die Eingabearrays int64 sind. Dies liefert vorhersagbarere, oft größere Index-dtypes in sparrays und weniger Casting zur Anpassung der dtypes.

  • Überprüfung des sparse Typs und Formats

    • issparse(A) gibt True für jedes sparse Array/Matrix zurück.

    • isspmatrix(M) gibt True für jede sparse Matrix zurück.

    • isspmatrix_csr(M) prüft auf eine sparse Matrix mit spezifischem Format. Sie sollte durch eine Array-kompatible Version ersetzt werden, wie z.B.:

    • issparse(A) and A.format == 'csr', was auf ein CSR sparse Array/Matrix prüft.

  • Umgang mit der API Ihres Softwarepakets mit sparse Ein-/Ausgabe

    • Die Eingaben sind relativ einfach, um sie mit spmatrix oder sparray zum Laufen zu bringen. Solange Sie A.multiply(B) für elementweise und A @ B für Matrixmultiplikation verwenden und sparse.linalg.matrix_power für Matrixpotenzen verwenden, sollten Sie nach Abschluss des "ersten Durchlaufs" der im nächsten Abschnitt beschriebenen Migrationsschritte in Ordnung sein. Ihr Code wird beide Arten von Eingaben austauschbar verarbeiten.

    • Die Migration von sparse Ausgaben aus Ihren Funktionen erfordert etwas mehr Überlegung. Erstellen Sie eine Liste aller Ihrer öffentlichen Funktionen, die spmatrix-Objekte zurückgeben. Prüfen Sie, ob Sie auch sparrays zurückgeben möchten. Das hängt von Ihrer Bibliothek und ihren Benutzern ab. Wenn Sie möchten, dass diese Funktionen weiterhin spmatrix- oder sparray-Objekte zurückgeben, können Sie dies oft mit einer sparse Eingabe tun, die auch als Signal für den zurückzugebenden Typ dient. Entwerfen Sie Ihre Funktion so, dass sie den eingegebenen Typ zurückgibt. Dieser Ansatz kann auf dichte Eingaben erweitert werden. Wenn die Eingabe eine np.matrix oder ein maskiertes Array mit np.matrix als seinem ._baseclass Attribut ist, geben Sie spmatrix zurück. Andernfalls geben Sie ein sparray zurück. Ohne solche Eingaben sind zwei weitere Ansätze, ein Schlüsselwortargument zu erstellen, um anzugeben, welches zurückgegeben werden soll, oder eine neue Funktion zu erstellen (wie wir es z.B. mit eye_array getan haben), die die gleiche grundlegende Syntax hat, aber ein sparray zurückgibt. Welche Methode Sie wählen, hängt von Ihrer Bibliothek, Ihren Benutzern und Ihren Präferenzen ab.

Details: Konstruktorfunktionen#

Diese vier Funktionen sind neu und verarbeiten nur sparrays: block_array, diags_array, eye_array und random_array. Ihre Signaturen sind

def block_array(blocks, format=None, dtype=None):
def diags_array(diagonals, /, *, offsets=0, shape=None, format=None, dtype=None):
def eye_array(m, n=None, *, k=0, dtype=float, format=None):
def random_array(shape, density=0.01, format='coo', dtype=None, rng=None, data_sampler=None):

Die Funktion random_array hat ein shape (2-Tupel) Argument anstelle von zwei ganzen Zahlen. Und das rng Argument hat standardmäßig NumPy's neues default_rng(). Dies unterscheidet sich von den spmatrix rand und random, die standardmäßig die globale RandomState-Instanz verwenden. Wenn Sie sich nicht viel um diese Dinge kümmern, sollte die Standardeinstellung gut funktionieren. Wenn Ihnen die Initialisierung Ihrer Zufallszahlen wichtig ist, sollten Sie diesem Aufruf beim Wechsel der Funktionen wahrscheinlich ein rng=... Schlüsselwortargument hinzufügen. Zusammenfassend lässt sich sagen: Um auf random_array zu migrieren, ändern Sie den Funktionsnamen, konvertieren Sie das shape-Argument in ein einzelnes Tupel-Argument, lassen Sie alle anderen Parameter wie zuvor und überlegen Sie, welche Art von rng=-Argument verwendet werden soll, falls überhaupt.

Die Funktion diags_array verwendet Keyword-only-Regeln für Argumente. Daher müssen Sie offsets= vor die Offsets-Argumente schreiben. Das scheint bei der Migration von der Verwendung von diags mühsam zu sein, aber es hilft, Verwirrung zu vermeiden und erleichtert das Lesen. Ein einzelner Shape-Parameter ersetzt auch hier zwei ganze Zahlen für diese Migration.

Bestehende Funktionen, die sorgfältig migriert werden müssen#

Diese Funktionen geben sparray oder spmatrix zurück, abhängig von den eingegebenen Typen: kron, kronsum, hstack, vstack, block_diag, tril und triu. Ihre Signaturen sind

def kron(A, B, format=None):
def kronsum(A, B, format=None):
def hstack(blocks, format=None, dtype=None):
def vstack(blocks, format=None, dtype=None):
def block_diag(mats, format=None, dtype=None):
def tril(A, k=0, format=None):
def triu(A, k=0, format=None):

Die Verwendung dieser Funktionen sollte überprüft und die Eingaben angepasst werden, um sicherzustellen, dass die Rückgabewerte sparrays sind. Und im Gegenzug sollten die Ausgaben als sparrays behandelt werden. Um sparrays zurückzugeben, muss mindestens eine Eingabe ein sparray sein. Wenn Sie Listen von Listen oder NumPy-Arrays als Eingabe verwenden, sollten Sie eines davon in ein sparse Array konvertieren, um sparse Arrays zu erhalten.

Funktionen, die für die Migration umbenannt wurden#

Funktion

Neue Funktion

Kommentare

eye

eye_array

identity

eye_array

diags

diags_array

Keyword-only-Eingabe

spdiags

dia_array

Shape als 2-Tupel

bmat

block

rand

random_array

Shape als 2-Tupel und default_rng

random

random_array

Shape als 2-Tupel und default_rng

Details: Formänderungen und Reduktionen#

  • Konstruktion mit 1D-Liste von Werten

    • csr_array([1, 2, 3]).shape == (3,) 1D-Eingabe erzeugt ein 1D-Array.

    • csr_matrix([1, 2, 3]).shape == (1, 3) 1D-Eingabe erzeugt eine 2D-Matrix.

  • Indexierung und Iteration

    • Die Indexierung von sparray erlaubt 1D-Objekte, die mit np.newaxis oder None zu 2D gemacht werden können. Z.B. ergibt A[3, None, :] eine 2D-Zeile. Die Indexierung eines 2D-sparrays mit implizitem (nicht gegebenem) Spaltenindex ergibt ein 1D-Ergebnis, z.B. A[3] (Hinweis: Am besten nicht tun - schreiben Sie es stattdessen als A[3, :]). Wenn Sie ein 2D-Ergebnis benötigen, verwenden Sie np.newaxis oder None in Ihrem Index, oder fassen Sie den ganzzahligen Index in eine Liste ein, für die Fancy-Indexing 2D ergibt, z.B. A[[3], :].

    • Iteration über sparse Objekte: next(M) liefert eine sparse 2D-Zeilenmatrix, next(A) liefert ein sparse 1D-Array.

  • Reduktionsoperationen entlang einer Achse reduzieren die Form

    • M.min(axis=1) gibt eine 2D-Zeilenmatrix des Minimums entlang der Achse 1 zurück.

    • A.min(axis=1) gibt ein 1D coo_array des Minimums entlang der Achse 1 zurück. Einige Reduktionen geben dichte Arrays/Matrizen anstelle von sparse zurück.

      Methode

      Ergebnis

      sum(axis)

      dense

      mean(axis)

      dense

      argmin(axis)

      dense

      argmax(axis)

      dense

      min(axis)

      sparse

      max(axis)

      sparse

      nanmin(axis)

      sparse

      nanmax(axis)

      sparse

    Im Allgemeinen führen 2D sparray-Eingaben zu 1D-Ergebnissen. 2D spmatrix-Eingaben führen zu 2D-Ergebnissen.

  • Einige Reduktionen geben einen Skalar zurück. Diese sollten sich wie zuvor verhalten und müssen bei der Migration nicht berücksichtigt werden. Z.B. A.min()

Entfernte Methoden und Attribute#

  • Die Methoden get_shape, getrow, getcol, asfptype, getnnz, getH und die Attribute .A und .H sind nur für spmatrices vorhanden, nicht für sparrays. Es wird empfohlen, ihre Verwendung durch Alternativen zu ersetzen, bevor Sie mit der Umstellung auf sparray beginnen.

    Funktion

    Alternative

    M.get_shape()

    A.shape

    M.getformat()

    A.format

    M.asfptype(…)

    A.astype(…)

    M.getmaxprint()

    A.maxprint

    M.getnnz()

    A.nnz

    M.getnnz(axis)

    A.count_nonzero(axis)

    M.getH()

    A.conj().T

    M.getrow(i)

    A[i, :]

    M.getcol(j)

    A[:, j]

    M.A

    A.toarray()

    M.H

    A.conj().T

  • Formzuweisung (M.shape = (2, 6)) ist für sparray nicht erlaubt. Stattdessen sollten Sie A.reshape verwenden.

  • M.getnnz() gibt die Anzahl der gespeicherten Werte zurück – nicht die Anzahl der Nicht-Null-Werte. A.nnz tut dasselbe. Um die Anzahl der Nicht-Null-Werte zu erhalten, verwenden Sie A.count_nonzero(). Dies ist nichts Neues für die Migration, kann aber verwirrend sein.

    Um vom axis-Parameter von M.getnnz(axis=...) zu migrieren, können Sie A.count_nonzero(axis=...) verwenden, aber es ist kein exakter Ersatz, da es Nicht-Null-Werte anstelle von gespeicherten Werten zählt. Der Unterschied ist die Anzahl der explizit gespeicherten Nullwerte. Wenn Sie wirklich die Anzahl der gespeicherten Werte pro Achse wünschen, benötigen Sie einige NumPy-Tools.

    Der Ansatz mit NumPy-Tools funktioniert für die Formate COO, CSR, CSC, also konvertieren Sie zu einem davon. Für CSR und CSC ist die Hauptachse komprimiert und np.diff(A.indptr) gibt ein dichtes 1D-Array mit der Anzahl der gespeicherten Werte für jeden Hauptachsenwert zurück (Zeile für CSR und Spalte für CSC). Die Nebenachsen können mit np.bincount(A.indices, minlength=N) berechnet werden, wobei N die Länge der Nebenachse ist (z.B. A.shape[1] für CSR). Die Funktion bincount funktioniert für jede Achse des COO-Formats unter Verwendung von A.coords[axis] anstelle von A.indices.

Tests verwenden, um * und ** Stellen zu finden#

  • Es kann schwierig sein, skalare Multiplikation * von Matrixmultiplikation * zu unterscheiden, während Sie Ihren Code migrieren. Python hat dies theoretisch gelöst, indem der Matrixmultiplikationsoperator @ eingeführt wurde. * wird für skalare Multiplikation verwendet, während @ für Matrixmultiplikation verwendet wird. Aber die Konvertierung von Ausdrücken, die * für beide verwenden, kann knifflig sein und zu Augenermüdung führen. Glücklicherweise, wenn Ihr Code eine Testsuite hat, die die auszudringenden Ausdrücke abdeckt, können Sie sie verwenden, um Stellen zu finden, an denen * für Matrixmultiplikation mit sparse Matrizen verwendet wird. Ändern Sie diese in @.

    Der Ansatz "monkey-patches" die dunder-Methoden der spmatrix-Klasse, um eine Ausnahme auszulösen, wenn * für Matrixmultiplikation verwendet wird (und nicht für skalare Multiplikation). Die Testsuite wird an diesen Stellen einen Fehler melden. Und ein Testfehler ist hier ein Erfolg, weil er zeigt, wo Änderungen vorgenommen werden müssen. Ändern Sie das fehlerhafte * in @, suchen Sie in der Nähe nach ähnlichen Änderungen und führen Sie die Tests erneut aus. Ähnlich hilft dieser Ansatz, Stellen zu finden, an denen ** für Matrixpotenz verwendet wird. SciPy löst eine Ausnahme aus, wenn @ für skalare Multiplikation verwendet wird, so dass dies Stellen erfasst, an denen Sie fälschlicherweise etwas geändert haben. Die Testsuite mit diesem Monkey-Patch prüft also auch die Korrekturen.

    Fügen Sie den folgenden Code zu Ihrer conftest.py Datei hinzu. Führen Sie dann Ihre Tests lokal aus. Wenn es viele Matrixausdrücke gibt, möchten Sie vielleicht einen Abschnitt Ihres Codes nach dem anderen testen. Ein schneller Blick auf den Code zeigt, dass er einen ValueError auslöst, wann immer * zwischen zwei matrixähnlichen Objekten (sparse oder dense) verwendet wird, und wann immer ** für Matrixpotenz verwendet wird. Außerdem gibt er eine Warnung aus, wann immer sum/mean/min/max/argmin/argmax mit einer Achse verwendet werden, so dass die Ausgabe bei spmatrix 2D und bei sparray 1D ist. Das bedeutet, dass Sie überprüfen müssen, ob der Code entweder 1D- oder 2D-Ausgaben über flatten/ravel, np.atleast_2d oder Indexierung verarbeiten kann.

    #================== Added to check spmatrix usage ========================
    import scipy
    from warnings import warn
    
    def flag_this_call(*args, **kwds):
        raise ValueError("Old spmatrix function names for rand/spdiags called")
    
    scipy.sparse._construct.rand = flag_this_call
    scipy.sparse._construct.spdiags = flag_this_call
    
    class _strict_mul_mixin:
        def __mul__(self, other):
            if not scipy.sparse._sputils.isscalarlike(other):
                raise ValueError('Operator * used here! Change to @?')
            return super().__mul__(other)
    
        def __rmul__(self, other):
            if not scipy.sparse._sputils.isscalarlike(other):
                raise ValueError('Operator * used here! Change to @?')
            return super().__rmul__(other)
    
        def __imul__(self, other):
            if not scipy.sparse._sputils.isscalarlike(other):
                raise ValueError('Operator * used here! Change to @?')
            return super().__imul__(other)
    
        def __pow__(self, *args, **kwargs):
            raise ValueError('spmatrix ** found! Use linalg.matrix_power?')
    
        @property
        def A(self):
            raise TypeError('spmatrix A property found! Use .toarray()')
    
        @property
        def H(self):
            raise TypeError('spmatrix H property found! Use .conjugate().T')
    
        def asfptype(self):
            raise TypeError('spmatrix asfptype found! rewrite needed')
    
        def get_shape(self):
            raise TypeError('spmatrix get_shape found! Use .shape')
    
        def getformat(self):
            raise TypeError('spmatrix getformat found! Use .format')
    
        def getmaxprint(self):
            raise TypeError('spmatrix getmaxprint found! Use .shape')
    
        def getnnz(self):
            raise TypeError('spmatrix getnnz found! Use .nnz')
    
        def getH(self):
            raise TypeError('spmatrix getH found! Use .conjugate().T')
    
        def getrow(self):
            raise TypeError('spmatrix getrow found! Use .row')
    
        def getcol(self):
            raise TypeError('spmatrix getcol found! Use .col')
    
        def sum(self, *args, **kwds):
            axis = args[0] if len(args)==1 else args if args else kwds.get("axis", None)
            if axis is not None:
                warn(f"\nMIGRATION WARNING: spmatrix sum found using axis={axis}. "
                     "\nsparray with a single axis will produce 1D output. "
                     "\nCheck nearby to ensure 1D output is handled OK in this spot.\n")
            print(f"{args=} {axis=} {kwds=}")
            return super().sum(*args, **kwds)
    
        def mean(self, *args, **kwds):
            axis = args[0] if len(args)==1 else args if args else kwds.get("axis", None)
            if axis is not None:
                warn(f"\nMIGRATION WARNING: spmatrix mean found using axis={axis}."
                     "\nsparray with a single axis will produce 1D output.\n"
                     "Check nearby to ensure 1D output is handled OK in this spot.\n")
            return super().mean(*args, **kwds)
    
        def min(self, *args, **kwds):
            axis = args[0] if len(args)==1 else args if args else kwds.get("axis", None)
            if axis is not None:
                warn(f"\nMIGRATION WARNING: spmatrix min found using axis={axis}."
                     "\nsparray with a single axis will produce 1D output. "
                     "Check nearby to ensure 1D output is handled OK in this spot.\n")
            return super().min(*args, **kwds)
    
        def max(self, *args, **kwds):
            axis = args[0] if len(args)==1 else args if args else kwds.get("axis", None)
            if axis is not None:
                warn(f"\nMIGRATION WARNING: spmatrix max found using axis={axis}."
                     "\nsparray with a single axis will produce 1D output. "
                     "Check nearby to ensure 1D output is handled OK in this spot.\n")
            return super().max(*args, **kwds)
    
        def argmin(self, *args, **kwds):
            axis = args[0] if len(args)==1 else args if args else kwds.get("axis", None)
            if axis is not None:
                warn(f"\nMIGRATION WARNING: spmatrix argmin found using axis={axis}."
                     "\nsparray with a single axis will produce 1D output. "
                     "Check nearby to ensure 1D output is handled OK in this spot.\n")
            return super().argmin(*args, **kwds)
    
        def argmax(self, *args, **kwds):
            axis = args[0] if len(args)==1 else args if args else kwds.get("axis", None)
            if axis is not None:
                warn(f"\nMIGRATION WARNING: spmatrix argmax found using axis={axis}."
                     "\nsparray with a single axis will produce 1D output. "
                     "Check nearby to ensure 1D output is handled OK in this spot.\n")
            return super().argmax(*args, **kwds)
    
    
    class coo_matrix_strict(_strict_mul_mixin, scipy.sparse.coo_matrix):
        pass
    
    class bsr_matrix_strict(_strict_mul_mixin, scipy.sparse.bsr_matrix):
        pass
    
    class csr_matrix_strict(_strict_mul_mixin, scipy.sparse.csr_matrix):
        pass
    
    class csc_matrix_strict(_strict_mul_mixin, scipy.sparse.csc_matrix):
        pass
    
    class dok_matrix_strict(_strict_mul_mixin, scipy.sparse.dok_matrix):
        pass
    
    class lil_matrix_strict(_strict_mul_mixin, scipy.sparse.lil_matrix):
        pass
    
    class dia_matrix_strict(_strict_mul_mixin, scipy.sparse.dia_matrix):
        pass
    
    scipy.sparse.coo_matrix = scipy.sparse._coo.coo_matrix = coo_matrix_strict
    scipy.sparse.bsr_matrix = scipy.sparse._bsr.bsr_matrix = bsr_matrix_strict
    scipy.sparse.csr_matrix = scipy.sparse._csr.csr_matrix = csr_matrix_strict
    scipy.sparse.csc_matrix = scipy.sparse._csc.csc_matrix = csc_matrix_strict
    scipy.sparse.dok_matrix = scipy.sparse._dok.dok_matrix = dok_matrix_strict
    scipy.sparse.lil_matrix = scipy.sparse._lil.lil_matrix = lil_matrix_strict
    scipy.sparse.dia_matrix = scipy.sparse._dia.dia_matrix = dia_matrix_strict
    
    scipy.sparse._compressed.csr_matrix = csr_matrix_strict
    
    scipy.sparse._construct.bsr_matrix = bsr_matrix_strict
    scipy.sparse._construct.coo_matrix = coo_matrix_strict
    scipy.sparse._construct.csc_matrix = csc_matrix_strict
    scipy.sparse._construct.csr_matrix = csr_matrix_strict
    scipy.sparse._construct.dia_matrix = dia_matrix_strict
    
    scipy.sparse._extract.coo_matrix = coo_matrix_strict
    
    scipy.sparse._matrix.bsr_matrix = bsr_matrix_strict
    scipy.sparse._matrix.coo_matrix = coo_matrix_strict
    scipy.sparse._matrix.csc_matrix = csc_matrix_strict
    scipy.sparse._matrix.csr_matrix = csr_matrix_strict
    scipy.sparse._matrix.dia_matrix = dia_matrix_strict
    scipy.sparse._matrix.dok_matrix = dok_matrix_strict
    scipy.sparse._matrix.lil_matrix = lil_matrix_strict
    
    del coo_matrix_strict
    del bsr_matrix_strict
    del csr_matrix_strict
    del csc_matrix_strict
    del dok_matrix_strict
    del lil_matrix_strict
    del dia_matrix_strict
    #==========================================
    

Index-Array-Dtypes#

Wenn Sie komprimierte Indizes an einen Konstruktor übergeben, z.B. csr_array((data, indices, indptr)), setzt sparse Arrays den Index-dtype, indem es nur den dtype der Index-Arrays prüft. Sparse Matrizen prüfen auch die Indexwerte und können zu int32 herunterskaliert werden (weitere Details siehe gh-18509). Das bedeutet, Sie können int64-Indizierung erhalten, wo Sie früher int32 hatten. Sie können dies steuern, indem Sie den dtype vor der Instanziierung festlegen oder nach der Konstruktion neu casten.

Zwei sparse Hilfsfunktionen können bei der Handhabung des Index-dtypes helfen. Verwenden Sie get_index_dtype(arrays, maxval, check_contents) während der Erstellung von Indizes, um einen geeigneten dtype (int32 oder int64) für Ihre komprimierten Indizes zu finden.

Verwenden Sie safely_cast_index_arrays(A, idx_dtype) zum Neucasten nach der Konstruktion, wobei Sie sicherstellen, dass Sie keine Überläufe beim Herunterskalieren erzeugen. Diese Funktion ändert das Eingabearray nicht tatsächlich. Die gecasteten Arrays werden zurückgegeben. Und Kopien werden nur bei Bedarf erstellt. Sie können also prüfen, ob ein Casting durchgeführt wurde, mit if indices is not A.indices:

Die Funktion Signaturen sind

def get_index_dtype(arrays=(), maxval=None, check_contents=False):
def safely_cast_index_arrays(A, idx_dtype=np.int32, msg=""):

Beispiel-Idiome umfassen die folgenden für get_index_dtype

.. code-block:: python

    # select index dtype before construction based on shape
    shape = (3, 3)
    idx_dtype = scipy.sparse.get_index_dtype(maxval=max(shape))
    indices = np.array([0, 1, 0], dtype=idx_dtype)
    indptr = np.arange(3, dtype=idx_dtype)
    A = csr_array((data, indices, indptr), shape=shape)

und für safely_cast_index_arrays

.. code-block:: python

    # rescast after construction, raising exception if shape too big
    indices, indptr = scipy.sparse.safely_cast_index_arrays(B, np.int32)
    B.indices, B.indptr = indices, indptr

Sonstiges#

  • Binäre Operatoren +, -, *, /, @, !=, > wirken auf sparse und/oder dichte Operanden

    • Wenn alle Eingaben sparse sind, ist die Ausgabe normalerweise auch sparse. Die Ausnahme ist /, das dense zurückgibt (Division durch den Standardwert 0 ist nan).

    • Wenn Eingaben gemischt sparse und dense sind, ist das Ergebnis normalerweise dense (d.h. np.ndarray). Ausnahmen sind *, das sparse ist, und /, das für dense / sparse nicht implementiert ist und sparse für sparse / dense zurückgibt.

  • Binäre Operatoren +, -, *, /, @, !=, > mit Array- und/oder Matrix-Operanden

    • Wenn alle Eingaben Arrays sind, sind die Ausgaben Arrays, und dasselbe gilt für Matrizen.

    • Beim Mischen von sparse Arrays mit sparse Matrizen gibt der führende Operand den Typ für die Ausgabe an, z.B. sparray + spmatrix ergibt ein sparse Array, während die Umkehrung der Reihenfolge ein sparse Matrix ergibt.

    • Beim Mischen von dense Matrizen mit sparse Arrays sind die Ergebnisse normalerweise Arrays mit Ausnahmen für Vergleiche, z.B. >, das dense Matrizen zurückgibt.

    • Beim Mischen von dense Arrays mit sparse Matrizen sind die Ergebnisse normalerweise Matrizen mit einer Ausnahme für array @ sparse matrix, die ein dense Array zurückgibt.