Boolean-Valued Indexing in Python
Cos'è la Boolean-Valued Indexing
Il Boolean-Valued Indexing è una tecnica che posso utilizzare nel linguaggio Python per selezionare gli elementi di un array che soddisfano una particolare condizione.
Ad esempio, creo un array tramite il modulo Numpy
>>> import numpy as np
>>> A = np.arange(10)
Nell'array A ci sono dieci elementi numerici.
>>> A
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
Per selezionare gli elementi maggiori di 5 mi basta scrivere
>>> A>5
Python mi restituisce un array con valori booleani indicandomi quali elementi dell'array A soddisfano la condizione A>5
array([False, False, False, False, False, False, True, True, True, True])
Per selezionare gli elementi digito
>>> A[A>5]
Il costrutto A>5 viene sostituito dall'array con i valori booleani [False, False, False, False, False, False, True, True, True, True]
In questo modo l'interprete restituisce solo gli elementi dell'array A che hanno valore booleano True
L'output è il seguente
array([6, 7, 8, 9])
Potrei usare la condizione anche per modificare contemporaneamente tutti gli elementi dell'array che soddisfano la condizione
Ad esempio, per azzerare tutti gli elementi dell'array A minori di 6 digito
>>> A[A<6]=0
Dopo la modifica il contenuto dell'array A è il seguente
>>> A
array([0, 0, 0, 0, 0, 0, 6, 7, 8, 9])
Faccio un altro esempio
Creo una matrice 3x3
>>> M=np.array([[1, 2, 3],[4, 5, 6], [7, 8, 9]])
Per selezionare la seconda e la terza colonna tramite il boolean-valued indexing digito
>>> M[:,np.array([False, True, True])]
Il risultato in output è
[[2 3]
[5 6]
[8 9]]
La differenza tra slicing e boolean-valued indexing
A differenza dell slicing, la selezione tramite la boolean-valued indexing registra i dati in uno spazio di memoria indipendente.
Quindi, se modifico i valori della selezione la modifica non si ripercuote sull'array di origine.
Ad esempio, salvo la selezione nella variabile B
>>> B=A[A>5]
Ora la variabile B è composta dai seguenti elementi
>>> B
array([6, 7, 8, 9])
Modifico il primo valore dell'array B
>>> B[0]=-1
L'array B viene modificato
>>> B
array([-1, 7, 8, 9])
L'array A invece non viene modificato perché si trova in altri indirizzi di memoria
>>> A
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
Cosa accade nel caso dello slicing?
Se avessi selezionato gli stessi elementi tramite lo slicing avrei compiuto una copia per riferimento puntando gli stessi spazi di memoria dell'array iniziale.
>>> B=A[6:]
>>> B
array([6, 7, 8, 9])
Pertanto, una qualsiasi modifica all'array B si ripercuote anche sull'array A perché i due array A e B puntano agli stessi indirizzi di memoria
>>> B[0]=-1
>>> B
array([-1, 7, 8, 9])
In questo caso anche l'array A viene modificato
>>> A
array([ 0, 1, 2, 3, 4, 5, -1, 7, 8, 9])
E così via.