Al intentar indexar una matriz 2D de forma [N, M] con dos máscaras booleanas 1D, formas N y M, ciertas combinaciones de Verdadero y Falso conducen a un error de transmisión (particularmente cuando uno es todo falso). No estoy seguro de si se espera este comportamiento, pero parece muy sorprendente e indeseable.
En el siguiente ejemplo, x[[False, True, True], [True, True, True]]
errores, mientras que x[[False, True, True], True]
y x[[False, True, True]]
tienen el comportamiento esperado.
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)
(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,)
1.16.2 3.6.8 |Anaconda, Inc.| (default, Dec 30 2018, 01:22:34)
[GCC 7.3.0]
Con matrices booleanas, el código asume que está tratando de indexar una sola dimensión o todos los elementos al mismo tiempo, con la opción, desafortunadamente, adivinada de una manera que permite eliminar un solo True
. Es decir, convierte su row_mask, col_mask
en una matriz booleana (2,3) y luego descubre que no puede indexar la matriz (3,3).
Parte del problema es que las tuplas y las listas se tratan como equivalentes, algo de lo que estamos tratando de alejarnos. Eventualmente, manejaría el índice de matriz booleana asegurándose de que la máscara fuera una lista doble.
Por ahora, sin embargo, me temo que la única solución es hacer x[row_mask][:, col_mask]
.
cc @ eric-wieser, quien ha estado trabajando para desaprobar el "tratar tupla como lista" para operaciones de indexación.
ps más molesto encuentro esta diferencia:
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,)
Sí, x[row_mask][:, col_mask]
es lo que terminé haciendo. Gracias por la explicación, me alegro de que sea algo que se está investigando.
Creo que arr[np.ix_(index)]
es lo que quiere / espera aquí, o en otras palabras sobre la lógica de indexación externa como en NEP 21: https://github.com/numpy/numpy/blob/master/doc/neps /nep-0021-advanced-indexing.rst
Tal vez eso se recupere en algún momento. La NEP también dice que al menos para la indexación actual, múltiples índices booleanos deberían estar en desuso (creo que si permitir este caso de uso específico aún puede haber sido cuestionado, es consistente, pero puede no tener muchos casos de uso y ser bastante confuso en cualquier caso).
Comentario más útil
Con matrices booleanas, el código asume que está tratando de indexar una sola dimensión o todos los elementos al mismo tiempo, con la opción, desafortunadamente, adivinada de una manera que permite eliminar un solo
True
. Es decir, convierte surow_mask, col_mask
en una matriz booleana (2,3) y luego descubre que no puede indexar la matriz (3,3).Parte del problema es que las tuplas y las listas se tratan como equivalentes, algo de lo que estamos tratando de alejarnos. Eventualmente, manejaría el índice de matriz booleana asegurándose de que la máscara fuera una lista doble.
Por ahora, sin embargo, me temo que la única solución es hacer
x[row_mask][:, col_mask]
.cc @ eric-wieser, quien ha estado trabajando para desaprobar el "tratar tupla como lista" para operaciones de indexación.
ps más molesto encuentro esta diferencia: