Numpy: Errores de transmisión con máscaras booleanas multidimensionales

Creado en 3 abr. 2019  ·  3Comentarios  ·  Fuente: numpy/numpy

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.

Ejemplo de código de reproducción:

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)

Mensaje de error:

     (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,)

Información de la versión de Numpy / Python:

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

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 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,) 

Todos 3 comentarios

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).

¿Fue útil esta página
0 / 5 - 0 calificaciones