Numpy: Übertragungsfehler mit mehrdimensionalen booleschen Masken

Erstellt am 3. Apr. 2019  ·  3Kommentare  ·  Quelle: numpy/numpy

Beim Versuch, ein 2D-Array der Form [N, M] mit zwei booleschen 1D-Masken, den Formen N und M, zu indizieren, führen bestimmte Kombinationen von True und False zu einem Übertragungsfehler (insbesondere wenn eine vollständig falsch ist). Ich bin mir nicht sicher, ob dieses Verhalten erwartet wird, aber es erscheint höchst überraschend und unerwünscht.

Im Beispiel unten treten x[[False, True, True], [True, True, True]] Fehler auf, während x[[False, True, True], True] und x[[False, True, True]] das erwartete Verhalten aufweisen.

Codebeispiel reproduzieren:

import numpy as np
from itertools import product

x = np.zeros((3,3))
mask_1d = [*product([True, False], repeat=3)]

for row_mask, col_mask in product(mask_1d, mask_1d):
    try:
        x[row_mask, col_mask]
    except IndexError as e:
        print(row_mask, col_mask)
        print(e)

Fehlermeldung:

     (True, True, True) (True, True, False)
shape mismatch: indexing arrays could not be broadcast together with shapes (3,) (2,) 
(True, True, True) (True, False, True)
shape mismatch: indexing arrays could not be broadcast together with shapes (3,) (2,) 
(True, True, True) (False, True, True)
shape mismatch: indexing arrays could not be broadcast together with shapes (3,) (2,) 
(True, True, True) (False, False, False)
shape mismatch: indexing arrays could not be broadcast together with shapes (3,) (0,) 
(True, True, False) (True, True, True)
shape mismatch: indexing arrays could not be broadcast together with shapes (2,) (3,) 
(True, True, False) (False, False, False)
shape mismatch: indexing arrays could not be broadcast together with shapes (2,) (0,) 
(True, False, True) (True, True, True)
shape mismatch: indexing arrays could not be broadcast together with shapes (2,) (3,) 
(True, False, True) (False, False, False)
shape mismatch: indexing arrays could not be broadcast together with shapes (2,) (0,) 
(False, True, True) (True, True, True)
shape mismatch: indexing arrays could not be broadcast together with shapes (2,) (3,) 
(False, True, True) (False, False, False)
shape mismatch: indexing arrays could not be broadcast together with shapes (2,) (0,) 
(False, False, False) (True, True, True)
shape mismatch: indexing arrays could not be broadcast together with shapes (0,) (3,) 
(False, False, False) (True, True, False)
shape mismatch: indexing arrays could not be broadcast together with shapes (0,) (2,) 
(False, False, False) (True, False, True)
shape mismatch: indexing arrays could not be broadcast together with shapes (0,) (2,) 
(False, False, False) (False, True, True)
shape mismatch: indexing arrays could not be broadcast together with shapes (0,) (2,)

Numpy/Python-Versionsinformationen:

1.16.2 3.6.8 |Anaconda, Inc.| (default, Dec 30 2018, 01:22:34) 
[GCC 7.3.0]

Hilfreichster Kommentar

Bei booleschen Arrays geht der Code davon aus, dass Sie versuchen, entweder eine einzelne Dimension oder alle Elemente gleichzeitig zu indizieren – wobei die Auswahl leider so erraten ist, dass ein einzelnes True entfernt werden kann. Dh, es verwandelt Ihr row_mask, col_mask in ein (2,3) boolesches Array und stellt dann fest, dass es das (3,3) Array nicht indizieren kann.

Ein Teil des Problems besteht darin, dass Tupel und Listen als gleichwertig behandelt werden, etwas, von dem wir versuchen, wegzukommen. Schließlich würden Sie den booleschen Array-Index handhaben, indem Sie sicherstellen, dass die Maske eine doppelte Liste ist.

Im Moment fürchte ich jedoch, dass die einzige Lösung darin besteht, x[row_mask][:, col_mask] zu tun.

cc @eric-wieser, der daran gearbeitet hat, das "Tupel als Liste behandeln" für Indizierungsoperationen als veraltet zu bezeichnen.

ps Am nervigsten finde ich diesen Unterschied:

x = np.arange(9).reshape(3, 3)
# x[[False, True, True], True]
# array([[3, 4, 5],
#        [6, 7, 8]])
x[[False, True, True], False]
# IndexError: shape mismatch: indexing arrays could not be broadcast together with shapes (2,) (0,) 

Alle 3 Kommentare

Bei booleschen Arrays geht der Code davon aus, dass Sie versuchen, entweder eine einzelne Dimension oder alle Elemente gleichzeitig zu indizieren – wobei die Auswahl leider so erraten ist, dass ein einzelnes True entfernt werden kann. Dh, es verwandelt Ihr row_mask, col_mask in ein (2,3) boolesches Array und stellt dann fest, dass es das (3,3) Array nicht indizieren kann.

Ein Teil des Problems besteht darin, dass Tupel und Listen als gleichwertig behandelt werden, etwas, von dem wir versuchen, wegzukommen. Schließlich würden Sie den booleschen Array-Index handhaben, indem Sie sicherstellen, dass die Maske eine doppelte Liste ist.

Im Moment fürchte ich jedoch, dass die einzige Lösung darin besteht, x[row_mask][:, col_mask] zu tun.

cc @eric-wieser, der daran gearbeitet hat, das "Tupel als Liste behandeln" für Indizierungsoperationen als veraltet zu bezeichnen.

ps Am nervigsten finde ich diesen Unterschied:

x = np.arange(9).reshape(3, 3)
# x[[False, True, True], True]
# array([[3, 4, 5],
#        [6, 7, 8]])
x[[False, True, True], False]
# IndexError: shape mismatch: indexing arrays could not be broadcast together with shapes (2,) (0,) 

Ja, x[row_mask][:, col_mask] ich letztendlich gemacht. Danke für die Erklärung, freut mich, dass man sich das ansieht.

Ich denke, arr[np.ix_(index)] ist das, was Sie hier wollen / erwarten, oder in anderen Worten zur äußeren Indexierungslogik wie in NEP 21: https://github.com/numpy/numpy/blob/master/doc/neps /nep-0021-advanced-indexing.rst

Vielleicht wird das irgendwann nachgeholt. Die NEP sagt auch, dass zumindest für die aktuelle Indizierung mehrere boolesche Indizes einfach veraltet sein sollten (ich denke, ob dieser spezielle Anwendungsfall zugelassen werden soll, ist möglicherweise noch umstritten – er ist konsistent, hat aber möglicherweise nicht viel Anwendungsfall und ist ziemlich verwirrend in auf jeden Fall).

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen