Vai al contenuto

Conteggio progressivo di ripetizioni↵

Come creare un campo calcolato che conta progressivamente le ripetizioni di valori in un CAMPO, ripartendo da 1 ogni volta che il valore cambia, come riportato nella colonna COUNT.

Esempio del risultato desiderato:↵

CAMPO COUNT
A 1
B 1
B 2
B 3
C 1
C 2
D 1
D 2
D 3

Soluzione con espressione↵

Espressione completa↵

with_variable('hist',
    array_slice(
        array_agg("CAMPO"),
        0,
        $id-1
    ),
    if(
        $id = 1,
        1,
        if(
            "CAMPO" = @hist[-1],
            array_length(@hist) - array_length(
                array_slice(
                    @hist,
                    0,
                    array_find(@hist, "CAMPO")
                )
            ) + 1,
            1
        )
    )
)

IMPORTANTE: Sostituire "CAMPO" con il nome effettivo del campo da analizzare.

Spiegazione dettagliata↵

1. Creazione dello storico dei valori precedenti↵

with_variable('hist',
    array_slice(
        array_agg("CAMPO"),
        0,
        $id-1
    ),
    ...
)

Cosa fa:

  • array_agg("CAMPO") → Crea un array con TUTTI i valori del campo dall'inizio del layer
  • array_slice(..., 0, $id-1) → Taglia l'array prendendo solo i valori dalla posizione 0 fino alla riga precedente a quella corrente
  • with_variable('hist', ...) → Salva questo array in una variabile chiamata @hist che possiamo riutilizzare

Esempio pratico:

Se siamo alla riga 4, @hist conterrà i valori delle righe 1, 2 e 3. Se il layer ha valori [A, B, B, B, C], alla riga 4 @hist = [A, B, B]

2. Controllo della prima riga↵

if($id = 1, 1, ...)

Cosa fa:

  • Se siamo alla prima riga del layer ($id = 1), restituisce semplicemente 1
  • Altrimenti, procede con il controllo successivo

Perché è necessario: La prima riga non ha valori precedenti da confrontare, quindi il conteggio parte sempre da 1

3. Confronto con il valore precedente↵

if("CAMPO" = @hist[-1], ..., 1)

Cosa fa:

  • @hist[-1] → Prende l'ultimo elemento dell'array (il valore della riga immediatamente precedente)
  • Confronta il valore corrente con quello precedente:
  • Se sono uguali → continua il conteggio (va al calcolo successivo)
  • Se sono diversi → restituisce 1 (ripartenza del conteggio)

Esempio pratico:

  • Riga 3 con valore "B", riga precedente aveva "B" → sono uguali, continua
  • Riga 5 con valore "C", riga precedente aveva "B" → sono diversi, restituisce 1

4. Calcolo del conteggio progressivo↵

array_length(@hist) - array_length(
    array_slice(
        @hist,
        0,
        array_find(@hist, "CAMPO")
    )
) + 1

Cosa fa (passo per passo):

  1. array_find(@hist, "CAMPO") → Cerca la prima occorrenza del valore corrente nell'array storico e restituisce la posizione (indice)

  2. array_slice(@hist, 0, array_find(@hist, "CAMPO")) → Taglia l'array dallo storico fino alla prima occorrenza del valore corrente. Questo rappresenta tutti i valori "prima" della sequenza corrente

  3. array_length(...) → Conta quanti elementi ci sono prima della sequenza corrente

  4. array_length(@hist) - array_length(...) + 1 → Sottrae dal totale degli elementi storici quelli prima della sequenza, aggiunge 1 per includere la riga corrente

Esempio numerico:

Supponiamo di essere alla riga 4 con valore "B":

  • @hist = [A, B, B] (prime 3 righe)
  • array_find(@hist, "B") = 1 (prima B trovata in posizione 1)
  • array_slice(@hist, 0, 1) = [A] (elementi prima della sequenza di B)
  • array_length([A]) = 1
  • array_length(@hist) = 3
  • Calcolo: 3 - 1 + 1 = 3 ← Terza ripetizione di "B"!

Come utilizzare l'espressione↵

Passaggi:↵

  1. Aprire la tabella degli attributi del layer
  2. Aprire il Calcolatore di Campi (icona dell'abaco o Ctrl+I)
  3. Configurare il nuovo campo:
  4. Crea un nuovo campo
  5. Nome campo: COUNT (o il nome che si preferisce)
  6. Tipo di campo: Numero intero (integer)
  7. Lunghezza: 10
  8. Incollare l'espressione nell'editor
  9. Modificare il nome del campo: sostituire tutte le occorrenze di "CAMPO" con il nome effettivo del campo da analizzare
  10. Cliccare OK per calcolare il campo

Note importanti↵

Ordine delle righe↵

L'espressione conta le ripetizioni nell'ordine in cui le righe appaiono nel layer. Se si vuole un ordine specifico:

  1. Prima di calcolare il campo, ordinare il layer:
  2. Cliccare con il tasto destro sull'intestazione del campo
  3. Scegliere "Ordina..."
  4. Selezionare ordine crescente o decrescente
  5. Poi calcolare il campo COUNT

Aggiornamento del campo↵

Se si modificano i dati o l'ordine delle righe dopo aver calcolato COUNT:

  • Il campo COUNT non si aggiornerà automaticamente
  • È necessario ricalcolarlo manualmente usando nuovamente l'espressione

Tipo di layer↵

L'espressione funziona con:

  • Shapefile
  • GeoPackage
  • Layer PostGIS
  • CSV/Delimitati
  • Qualsiasi layer vettoriale

Soluzioni alternative↵

Metodo 1: Espressione semplificata con array_sort↵

Una soluzione più semplice e leggibile che utilizza le funzioni di aggregazione e ordinamento:

array_find(
    array_sort(
        array_agg( $id, group_by:= "CAMPO" )
    ),
    $id
) + 1

Cosa fa:

  • array_agg($id, group_by:="CAMPO") → Crea un array con tutti gli ID delle righe raggruppate per valore del campo
  • array_sort(...) → Ordina gli ID in modo crescente
  • array_find(..., $id) → Trova la posizione dell'ID corrente nell'array ordinato
  • + 1 → Aggiunge 1 perché gli indici degli array partono da 0

Vantaggi:

  • Molto più semplice e leggibile
  • Più efficiente in termini di performance
  • Non necessita di gestire manualmente lo storico

Esempio pratico:

Per una riga con valore "B" e ID 3:

  • array_agg($id, group_by:="CAMPO") → [2, 3, 4] (tutti gli ID con valore "B")
  • array_sort([2, 3, 4]) → [2, 3, 4] (già ordinati)
  • array_find([2, 3, 4], 3) → 1 (posizione di ID 3)
  • 1 + 1 → 2 (secondo elemento con valore "B")

IMPORTANTE: Anche in questo caso, sostituire "CAMPO" con il nome effettivo del campo.

Metodo 2: Virtual Layer (SQL)↵

Se si preferisce usare SQL standard, è possibile creare un Virtual Layer:

Menu: Layer → Aggiungi Layer → Aggiungi/Modifica Virtual Layer

SELECT *,
  ROW_NUMBER() OVER (PARTITION BY CAMPO ORDER BY rowid) as COUNT
FROM nome_del_tuo_layer

Vantaggi:

  • Sintassi SQL standard (window functions)
  • Più leggibile
  • Più efficiente su grandi dataset

Svantaggi:

  • Crea un nuovo layer virtuale (non modifica l'originale)
  • Richiede di specificare esplicitamente l'ordinamento

Quale soluzione scegliere?↵

  • Espressione semplificata (Metodo 1): Ideale per la maggior parte dei casi, semplice e veloce
  • Espressione completa: Utile quando serve maggiore controllo sull'ordine delle righe basato su $id
  • Virtual Layer (Metodo 2): Preferibile per dataset molto grandi o quando si lavora già con SQL

Funzioni e variabili utilizzate: