Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

Stacking e splitting degli ndarray

In questa lezione introdurremo i concetti di stacking e splitting tramite NumPy definendo un insieme di esempi in merito.
In questa lezione introdurremo i concetti di stacking e splitting tramite NumPy definendo un insieme di esempi in merito.
Link copiato negli appunti

In questa lezione introdurremo i concetti di stacking e splitting tramite NumPy definendo un insieme di esempi in merito.

Stacking di ndarray

L’operazione di stacking è una tra le principali operazioni che non possono mancare nel proprio bagaglio di conoscenze quando è necessario manipolare un ndarray. Questa permette infatti di compiere l’unione tra ndarray aventi le stesse dimensioni secondo un asse definito.

Per compiere lo stack tra ndarray, NumPy offre diverse funzioni. Vediamole brevemente.

Metodo Descrizione
stack() effettua lo stacking tra due ndarray
hstack() esegue lo stacking orizzontale insieme alle colonne
vstack() esegue lo stacking verticale lungo le righe
dstack() esegue lo stacking approfondito lungo un nuovo terzo asse

Lo stack prende in ingresso tre parametri che sono:

  • una tupla di ndarray che si vuole unire;
  • l’asse attorno al quale compiere l’operazione.

Vediamo alcuni esempi prendendo in considerazione i seguenti ndarray.

v1 = np.array((1,2,3))
v2 = np.array((4,5,6))
a = np.array([[1,2],[3,4]])
b = np.array([[5,6],[7,8]])

Utilizziamo adesso la funzione di stack tra i due ndarray v1 e v2 su entrambi gli assi di interesse.

np.stack((v1,v2),axis=0)
> array([[1, 2, 3],
           [4, 5, 6]])
np.stack((v1,v2),axis=1)
> array([[1, 4],
            [2, 5],
            [3, 6]])

In entrambi i casi, abbiamo potuto unire tra loro i vettori di interesse, ottenendo nel primo caso una matrice 2x3 e nel secondo una 3x2.
Se invece facessimo lo stack tra gli ndarray a e b sull’asse 0, otterremmo un tensore (2, 2, 2) come segue.

np.stack((a,b),axis=0)
> array([[[1, 2],
            [3, 4]],
            [[5, 6],
            [7, 8]]])

Vediamo adesso alcuni esempi per le funzioni vstack(), hstack() e dstack().

La funzione vstack()() è necessaria quando vanno concatenati in sequenza gli ndarray in un ordine verticale, ossia lungo le righe. Il vertical stacking genera errore quando il numero di colonne non è uguale in entrambi gli ndarray.

np.vstack()((a,b))
> array([[1, 2],
            [3, 4],
            [5, 6],
            [7, 8]])

La funzione hstack() è invece usata per concatenare gli ndarray in ordine orizzontale, ossia lungo le colonne. Non è possibile eseguire l’horizontal stacking se il numero di righe non è uguale in entrambi gli array.

np.hstack((a,b))
> array([[1, 2, 5, 6],
    [3, 4, 7, 8]])

Infine, tramite la funzione dstack() possiamo unire gli ndarray tra di loro ottenendo una nuova dimensione.

np.dstack((a,b))
>  array([[[1, 5],
    [2, 6]],
    [[3, 7],
    [4, 8]]])

Splitting di un ndarray

Come per l’operazione di stacking, anche l’operazione di splitting rientra nell’ampio panorama di operazioni di manipolazione degli ndarray offerta da NumPy.

Per compiere lo split di un ndarray, NumPy offre diverse funzioni. Vediamole brevemente.

Metodo Descrizione
split() divide un array in più sotto-array di uguale dimensione
array_split() divide un array in più sotto-array di dimensioni uguali o quasi uguali. Non solleva un'eccezione se non è possibile effettuare una divisione equa
hsplit() divide un array in più sotto-array orizzontalmente (per colonna)
vsplit() divide l'array in più sotto-array verticalmente (per riga)
dsplit() divide un array in più sotto-array lungo la dimensione d scelta (profondità)

Pertanto, a seconda del metodo usato, sarà possibile suddividere l’array in modo diverso. Vediamo quindi qualche esempio e partiamo dalla funzione di split().

Lo split prende in ingresso tre parametri che sono:

  • ndarray che si vuole dividere;
  • l’indice o la sezione (può essere un intero o un vettore);
  • l’asse attorno al quale fare lo split.

Creiamo quindi un vettore di 10 elementi.

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

Applichiamo su questo lo split.

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

Il risultato è una lista di ndarray. ognuna composta da 2 elementi. Se provassimo a usare un valore diverso da 2 o 5 ci verrebbe restituito l’errore:

ValueError: array split does not result in an equal division

che sottolinea l’impossibilità di suddividere il vettore in modo non equo.

Usando invece un vettore contenente gli indici da usare per lo split, otterremo sempre una lista di ndarray di diversa dimensione come nell’esempio seguente.

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

Nell’esempio riportato, abbiamo suddiviso il vettore in quattro parti usando gli indici come indicatori.

Lo split su una matrice è simile a quanto visto finora, ma è sempre necessario passare una lista di indici che andranno a indicare la riga e la colonna su cui effettuare la suddivisione.

Supponendo di avere la seguente matrice 4x4 che va da 0 a 15, effettuiamo lo split passando la lista di indici [1, 3]

m = np.arange(16).reshape(4,4)
np.split(m, [1,3])
> [array([[0, 1, 2, 3]]), array([[ 4,  5,  6,  7],
            [ 8,  9, 10, 11]]), array([[12, 13, 14, 15]])

Il risultato è sempre una lista di tre ndarray di dimensione variabile in base alla suddivisione degli indici fornita.

La funzione di array_split() ha un comportamento simile a quella dello split con la differenza che non genera errore se si cerca di dividere un ndarray in partizioni diverse. Vediamo un semplice esempio in cui dividiamo la matrice m precedentemente generata in 3 parti uguali.

np.array_split(m,3)
> [array([[0, 1, 2, 3],[4, 5, 6, 7]]), array([[ 8,  9, 10, 11]]), array([[12, 13, 14, 15]])]

Come si può notare, il primo ndarray si compone di due delle prime due righe della matrice iniziale ottenendo così una suddivisione non bilanciata della matrice.
Se provassimo a compiere la medesima operazione con split(), verrebbe generato un errore.

Le funzioni di hsplit() e vsplit() si comportano in modo simile a quanto visto con split(). In particolare, hsplit() corrisponde allo split() impostando la variabile axis=1. Al contrario, vsplit() corrisponderà alla funzione di split() impostando axis=0. Pertanto possiamo vedere queste funzioni come degli “alias” di split().
Vediamo un esempio per la funzione vsplit().

Data la matrice 6x4 con valori che vanno da 0 a 23, suddividiamo in 3 parti uguali la matrice.

m1 = np.arange(24).reshape(6, 4)
np.vsplit(m1,3)
> [array([[0, 1, 2, 3],
            [4, 5, 6, 7]]),
        array([[ 8,  9, 10, 11],
            [12, 13, 14, 15]]),
        array([[16, 17, 18, 19],
            [20, 21, 22, 23]])]

Ultima, ma non per importanza, è la funzione dsplit() per effettuare l’operazione di split con axis=2. Questa funzione è infatti utile quando si lavora sui tensori.

Dato il tensore

t = np.arange(24).rehape(2, 2, 6)

dividiamolo in tre matrici di dimensioni variabili

np.dsplit(t, [2, 4])
> [array([[[ 0,  1],
            [ 6,  7]],
            [[12, 13],
            [18, 19]]]),
        array([[[ 2,  3],
            [ 8,  9]],
            [[14, 15],
            [20, 21]]]),
        array([[[ 4,  5],
            [10, 11]],
            [[16, 17],
            [22, 23]]])]

Il codice di questa lezione è disponibile su Github.

Ti consigliamo anche