Nella micro-lezione precedente abbiamo visto come stimare i valori mancanti con interpolate() e il suo metodo lineare, quello di default.

In questa micro-lezione approfondiremo tutti i metodi che possiamo applicare a interpolate().

Il dataframe di esempio

Per prima cosa importiamo le librerie:

import pandas as pd
import numpy as np

Useremo un dataset di misurazioni giornaliere di temperatura e vendite, con alcuni buchi:

df = pd.DataFrame({
    'giorno': pd.date_range('2024-01-01', periods=7),
    'temperatura': [5.0, np.nan, np.nan, 11.0, np.nan, 17.0, 20.0],
    'vendite':     [100, np.nan, np.nan, np.nan, 500, np.nan, 700]
})

Ecco l’aspetto del nostro dataframe:

giorno

temperatura

vendite

2024-01-01

5.0

100.0

2024-01-02

NaN

NaN

2024-01-03

NaN

NaN

2024-01-04

11.0

NaN

2024-01-05

NaN

500.0

2024-01-06

17.0

NaN

2024-01-07

20.0

700.0

Il metodo linear

Questo è il metodo di default. Assume che tra due punti noti i valori si muovano in maniera uniforme.

Sostanzialmente, questo metodo riempie i buchi tracciando una linea retta immaginaria tra i due valori noti prima e dopo dei valori nulli.

Ecco come usarlo:

df['temperatura'].interpolate(method='linear', inplace=True)

Quando usarlo: dati che crescono o calano in modo abbastanza regolare e prevedibile. Ideale per temperature, prezzi stabili, metriche che cambiano gradualmente.

Attenzione!

linear tratta ogni punto come equidistante dagli altri, indipendentemente dall'indice. Se l'indice è una data con buchi (es. mancano giorni festivi), usa invece method='time' (lo vedremo in seguito).

Il metodo index

L’idea dietro il metodo index è semplice: invece di dare per scontato che i punti siano equidistanti, usa i valori dell’indice come distanze reali.

Ecco come usarlo:

df['temperatura'].interpolate(method='index', inplace=True)

Quando usarlo: quando l'indice ha un significato numerico reale (chilometri, ore, prezzi...) e i dati non sono spaziati uniformemente.

Se invece l’indice del dataframe è composto da date o orari, puoi usare il metodo time che vedremo verso la fine di questa micro-lezione.

Il metodo polynomial

Invece di una retta, il metodo polynomial usa una curva polinomiale che passa per tutti i punti noti del nostro dataset. Il parametro order è obbligatorio.

Ecco come usarlo:

df['temperatura'].interpolate(method='polynomial', order=2, inplace=True)

I valori stimati non sono più equidistanti: la curva accelera leggermente seguendo l'andamento reale dei dati. I gradi più usati in pratica sono:

  • order=2 (quadratica): buona per curve a U o a campana, con accelerazione costante

  • order=3 (cubica): più flessibile, segue andamenti con un punto di flesso

  • Oltre il 3: raramente utile, rischia di creare oscillazioni artificiose tra i punti noti

Quando usarlo: dati che seguono un andamento curvo misurabile: la crescita di una pianta, una curva di apprendimento, dei consumi energetici stagionali, ecc.

Nota bene:

Più punti noti hai, meglio il metodo polinomiale lavora. Con pochi dati e un order alto, la curva può impazzire tra un punto e l'altro. Questo fenomeno si chiama overfitting.

Il metodo spline

Il metodo spline è simile al polinomiale, ma invece di usare una sola curva per tutti i punti, costruisce curve separate tra ogni coppia di punti noti e le raccorda in modo che la transizione sia fluida. Anche qui serve il parametro order.

Ecco come possiamo usarlo:

df['temperatura'].interpolate(method='spline', order=3, inplace=True)

Il metodo spline è generalmente più stabile del polinomiale: non oscilla tra i punti e produce transizioni più naturali, specialmente con serie più lunghe.

Quando usarlo: serie temporali fisiche o biologiche dove l'andamento deve apparire fluido e continuo. Ad esempio se lavoriamo con segnali di sensori o dati audio. È la scelta migliore quando hai molti punti noti e vuoi un risultato visivamente pulito.

Nota bene:

La differenza pratica tra polynomial e spline diventa evidente con serie lunghe (20+ punti). Su dataset piccoli i risultati sono molto simili.

I metodi ffill e bfill

Questi due metodi non stimano nulla, copiano semplicemente il valore più vicino disponibile.

ffill(forward fill) propaga il valore precedente in avanti, bfill (backward fill) fa il contrario: usa il valore successivo.

Ecco come usarli:

#forward fill
df['vendite'].interpolate(method='ffill', inplace=True)

#backward fill
df['vendite'].interpolate(method='bfill', inplace=True)

Quando usarli: ffill è perfetto quando il dato più recente è la stima migliore: il prezzo di un'azione nei giorni festivi in cui la borsa è chiusa rimane quello dell'ultimo giorno lavorativo. bfill ha senso quando i dati vengono registrati con ritardo e il valore successivo è quello più affidabile.

Il metodo time

Questo metodo funziona solo se l'indice del dataframe è una data o un orario. Fa la stessa cosa del lineare, ma tiene conto della distanza reale tra le date, non del semplice numero di righe.

Ecco come usarlo:

df_t = df.set_index('giorno')
    
df_t['temperatura'].interpolate(method='time', inplace=True)

Quando usarlo: ogni volta che il dataset ha buchi non uniformi nel tempo. Immagina dati settimanali con alcune settimane mancanti: con il metodo linear ogni buco ha lo stesso valore indipendentemente da quanti giorni mancano davvero; con il metodo time, un buco di 14 giorni viene stimato diversamente da uno di 7. Perfetto per prezzi di mercato, dati meteo o qualsiasi dataset basato su date e/o orari.

Attenzione!

Se l'indice non è di tipo datetime, pandas restituisce un errore. Verifica con df.index.dtype prima di usare questo metodo.

Come scegliere il metodo giusto

La scelta dipende principalmente da tre domande:

  1. Cosa descrivono i tuoi dati?

  2. Come si comportano i tuoi dati? Che andamento hanno?

  3. Quanti punti noti hai?

Se i dati cambiano in modo regolare e prevedibile, linear è quasi sempre sufficiente. Se sai che i dati seguono una curva, prova polynomial con order=2 o order=3.

Se hai una serie lunga e vuoi un risultato visivamente fluido, spline è la scelta migliore. Se il dato “rimane fermo” finché non cambia (come un prezzo o una categoria) ffill è più indicato degli altri metodi perché non inventa una progressione che non esiste.

E se lavori con date non uniformi, time è l'unico che rispetta davvero la struttura temporale dei dati.

Alla prossima micro-lezione 👋

Se vuoi imparare la data analysis con micro-lezioni che vanno dritto al sodo, iscriviti alla newsletter: