Fancy Indexing in Python

Cos'è la fancy indexing

La fancy indexing è una tecnica usata per accedere contemporaneamente a più elementi di un array creato con numpy.

Per accedere agli elementi utilizzo un array di indici.

Ad esempio, creo un array con 10 numeri

>>> import numpy as np
>>> A = np.linspace(0, 9, 10)

L'array A è composto da dieci numeri a zero a nove

>>> A
array([0., 1., 2., 3., 4., 5., 6., 7., 8., 9.])

Per accedere al secondo, al quarto e al sesto elemento in modo tradizionale dovrei digitare [ A [ 1 ], A [ 3 ], A [ 5 ]]

>>>[ A [ 1 ], A [ 3 ], A [ 5 ]]
[1.0, 3.0, 5.0]

In alternativa, posso accedere agli stessi elementi passando una lista o un array di indici

>>>ind = [1,3,5]
>>> A[ind]
array([1., 3., 5.])

Il risultato della fancy indexing prende la forma dell'array di indici.

Quindi, posso anche selezionare degli elementi e disporli in una diversa dimensione.

Ad esempio, seleziono i primi quattro elementi dell'array e li dispongo in una matrice quadrata 2x2

>>> ind=np.array([[0,1],[2,3]])
>>> A[ind]
array([[0., 1.],
[2., 3.]])

Allo stesso modo posso estrarre i dati da una matrice.

Ad esempio, creo un array a due dimensioni

>>> M=np.array([[1,2,3],[4,5,6],[7,8,9]])
>>> M
array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])

Poi definisco altri due array per indicare gli indici delle righe e delle colonne da selezionare

>>> riga=np.array([0,2,1])
>>> colonna=np.array([2,1,0])

Infine, passo gli indici riga e colonna per selezionare gli elementi della matrice M[0,2], M[2,1], M[1,0] digitando M[riga,colonna]

>>> M[riga,colonna]
array([3, 8, 4])

    La differenza tra slicing e fancy indexing

    La selezione tramite la fancy indexing assegna i dati in uno spazio di memoria indipendente dall'array di origine.

    Quindi, se modifico i valori della selezione la modifica non si ripercuote sull'array di origine.

    Ad esempio creo un array A

    >>> A = np.arange(10)

    L'array A è composto da dieci elementi

    >>> A
    array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

    Seleziono gli elementi con indice pari [2,4,6,8] tramite il fancy indexing e li salvo nell'array B

    >>> B=A[[2,4,6,8]]

    L'array B è composto dai seguenti elementi

    >>> B
    array([2, 4, 6, 8])

    Ora modifico il primo elemento dell'array B

    >>> B[0]=-1

    Il contenuto dell'array B è cambiato

    >>> B
    array([-1, 4, 6, 8])

    Il contenuto dell'array A è invece lo stesso perché si trova in un indirizzo di memoria differente

    >>> A
    array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

    Cosa accade nel caso dello slicing?

    La selezione tramite lo slicing avviene per riferimento. Questo vuol dire che la selezione punta agli stessi indirizzi di memoria dell'array iniziale.

    Quindi, una qualsiasi modifica alla selezione si ripercuote anche sull'array di origine.

    Ad esempio, seleziono gli elementi dell'array A con indice pari tramite lo slicing e assegno la selezione alla variabile B

    >>> B=A[2::2]

    L'array B è composto da quattro elementi

    >>> B
    array([2, 4, 6, 8])

    L'array B non contiene i dati ma i riferimenti agli indirizzi di memoria dei dati dell'array A.

    Pertanto, se modifico un elemento dell'array B

    >>> B[0]=-1

    la modifica cambia sia il contenuto dell'array B che dell'array iniziale A

    >>> B
    array([-1, 4, 6, 8])

    >>> A
    array([ 0, 1, -1, 3, 4, 5, 6, 7, 8, 9])

    perché i due array A e B puntano a dati fisici che si trovano allo stesso indirizzo di memoria nella RAM del computer.

    E così via.

     


     

    Segnalami un errore, un refuso o un suggerimento per migliorare gli appunti

    FacebookTwitterLinkedinLinkedin
    knowledge base

    Array con Numpy (Python)

    Alcune funzioni utili