¿Por qué obtenemos este resultado para la indexación booleana doble en Numpy?

¿Me sorprendió el resultado de la última expresión?

>>> from numpy import array, arange >>> a = arange(12).reshape(3,4) >>> b1 = array([False,True,True]) # first dim selection >>> b2 = array([True,False,True,False]) # second dim selection >>> >>> a[b1,:] # selecting rows array([[ 4, 5, 6, 7], [ 8, 9, 10, 11]]) >>> >>> a[b1] # same thing array([[ 4, 5, 6, 7], [ 8, 9, 10, 11]]) >>> >>> a[:,b2] # selecting columns array([[ 0, 2], [ 4, 6], [ 8, 10]]) >>> >>> a[b1,b2] # a weird thing to do array([ 4, 10]) 

Esperaba:

 array([[ 4, 6], [ 8, 10]]) 

¿Tienes alguna explicación de por qué es así?

Comencemos con su matriz:

 a = np.array([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11]]) 

Su lógica de indexación actual equivale a lo siguiente:

 a[[1, 2], [0, 2]] # array([ 4, 10]) 

Numpy, que se ajusta a 2 dimensiones, interpreta esto como índices indexados de dim1 [1, 2] e índices dim2 [0, 2] , o coordenadas (1, 0) y (2, 2) . No hay transmisión involucrada aquí.

Para permitir la difusión con matrices booleanas, puede usar numpy.ix_ :

 res = a[np.ix_(b1, b2)] print(res) array([[ 4, 6], [ 8, 10]]) 

La magia que ix_ realiza se indica en los documentos : “Las secuencias booleanas se interpretarán como máscaras booleanas para la dimensión correspondiente (equivalente a pasar np.nonzero(boolean_sequence) )”.

 print(np.ix_(b1, b2)) (array([[1], [2]], dtype=int64), array([[0, 2]], dtype=int64)) 

Como nota al margen, puede usar un enfoque más directo si tiene índices enteros:

 b1 = np.array([1, 2]) b2 = np.array([0, 2]) a[b1[:, None], b2] 

Ver también: pregunta relacionada sobre por qué este método no funciona con matrices booleanas.