Come Gestire le Covariate in Statistica: Dalla Regressione ai Modelli a Effetti Misti in Python

Cerca:

Generic selectors
Exact matches only
Search in title
Search in content
Post Type Selectors
cos'è una covariata statistica

Quante volte ci è capitato di guardare il coefficiente di un modello e chiederci:

“Ma questo è l’effetto reale, o c’è sotto qualcos’altro?”

Lavorare con i dati significa fare costantemente i conti con il rumore e con variabili che si intrecciano tra loro.

L’istinto, spesso, ci suggerisce di buttare nel calderone del modello tutte le variabili a disposizione per “controllare” il più possibile.

Eppure, aggiungere una variabile non è mai un’operazione neutra.

In statistica, quando inseriamo una variabile extra per pulire il nostro segnale o per ridurre la varianza, stiamo maneggiando una covariata. Non si tratta di un semplice trucco matematico per alzare l'[math]R^2[/math], ma di una lente che cambia letteralmente la domanda a cui il nostro modello sta rispondendo.

In questo articolo imparerai a:

  • Distinguere tra covariata e confondente
  • Stimare l’effetto di una covariata continua in una regressione lineare e riconoscere l’omitted variable bias
  • Condurre un’ANCOVA in Python, verificare l’assunzione delle pendenze parallele e confrontare codifiche ordinali e categoriche
  • Gestire covariate time-varying in studi longitudinali con Linear Mixed Models
  • Separare effetti between-person e within-person e interpretare l’ICC
  • Scegliere il modello adeguato in base alla struttura dei dati
Pubblicità

1. Cos’è una covariata?

In statistica, una covariata è una variabile che viene inclusa in un modello insieme alla variabile esplicativa principale e alla variabile risposta.

Immaginiamo di voler studiare l’effetto di un trattamento [math]T[/math] su un outcome [math]Y[/math]. Un modello lineare semplice è:

[math]\displaystyle Y_i = \beta_0 + \beta_1 T_i + \varepsilon_i[/math]

Se esiste una seconda variabile [math]X[/math] — per esempio l’età del soggetto — possiamo scrivere:

[math]\displaystyle Y_i = \beta_0 + \beta_1 T_i + \beta_2 X_i + \varepsilon_i[/math]

Qui [math]X[/math] è una covariata. Il coefficiente [math]\beta_1[/math] rappresenta l’associazione tra trattamento e outcome a parità di covariata inclusa nel modello.

Covariata e confondente non sono sinonimi

Questa distinzione è fondamentale.

Una covariata è una variabile inserita nel modello.

Un confondente è una variabile che, in un problema causale specifico, è associata sia all’esposizione/trattamento sia all’outcome e può distorcere la relazione osservata.

Una variabile confondente può essere utilizzata come covariata, ma non tutte le covariate sono confondenti. Per esempio, in uno studio randomizzato l’età può essere una covariata prognostica anche quando la randomizzazione ha già eliminato il confondimento sistematico.


2. Esercizio 1 — Regressione lineare con covariata continua

Il problema

Un’azienda farmaceutica testa un farmaco per ridurre la pressione sanguigna. Vengono reclutati 200 pazienti e raccolte:

  • pressione sistolica dopo 3 mesi
  • tipo di trattamento (farmaco o placebo)
  • età del paziente

La domanda: perché l’età dovrebbe essere considerata una covariata? E cosa succede se viene ignorata?

Simuliamo i dati con omitted variable bias

Per capire il problema costruiamo artificialmente un dataset in cui il trattamento è correlato all’età: i pazienti più anziani hanno maggiore probabilità di ricevere il farmaco. Questo scenario è realistico in studi osservazionali o in campioni randomizzati di piccole dimensioni dove si verificano sbilanciamenti casuali.

import numpy as np
import pandas as pd
from sklearn.linear_model import LinearRegression

np.random.seed(42)
n = 200

eta = np.random.uniform(50, 80, n)

# Pazienti più anziani hanno maggiore probabilità di ricevere il farmaco
prob_tratt = 0.2 + 0.6 * (eta - 50) / 30
trattamento = (np.random.uniform(0, 1, n) < prob_tratt).astype(int)

# Modello generativo vero
pressione = (
    120
    + 10 * trattamento      # vero effetto del farmaco
    + 0.5 * eta             # effetto dell'età
    + np.random.normal(0, 5, n)
)

df = pd.DataFrame({
    "pressione": pressione,
    "trattamento": trattamento,
    "eta": eta
})

Il vantaggio della simulazione è che conosciamo la verità generativa: effetto del trattamento = 10, effetto dell’età = 0.5.

Modello 1: ignoriamo la covariata

X1 = df[["trattamento"]]
y = df["pressione"]

mod1 = LinearRegression().fit(X1, y)
print(f"Coefficiente trattamento: {mod1.coef_[0]:.2f}")
print(f"R²: {mod1.score(X1, y):.3f}")

Output:

Coefficiente trattamento: 13.41
R²: 0.523

Il valore stimato (13.41) è superiore al vero effetto di 10. Questo è l’omitted variable bias: poiché il trattamento è correlato positivamente con l’età, e l’età aumenta la pressione, il coefficiente del trattamento assorbe anche parte dell’effetto dell’età.

Modello 2: inseriamo la covariata

X2 = df[["trattamento", "eta"]]
mod2 = LinearRegression().fit(X2, y)

print(f"Coefficiente trattamento: {mod2.coef_[0]:.2f}")
print(f"Coefficiente età: {mod2.coef_[1]:.2f}")
print(f"R²: {mod2.score(X2, y):.3f}")

Output:

Coefficiente trattamento: 10.20
Coefficiente età: 0.50
R²: 0.718

Il modello con covariata recupera molto bene la struttura generativa. Il coefficiente del trattamento si avvicina al vero valore 10, e l'[math]R^2[/math] aumenta da 0.523 a 0.718.

Controllo delle assunzioni

Prima di fidarci dei coefficienti, verifichiamo visivamente che la relazione tra età e pressione sia approssimativamente lineare in entrambi i gruppi:

import seaborn as sns
import matplotlib.pyplot as plt

sns.lmplot(x='eta', y='pressione', hue='trattamento', data=df,
           palette={0: '#E74C3C', 1: '#3498DB'}, height=5, aspect=1.2)
plt.title('Regressione di pressione su età, per gruppo')
plt.show()

Se le rette nei due gruppi fossero chiaramente non parallele, dovremmo considerare un’interazione [math]\text{trattamento} \times \text{età}[/math].

Forse potrebbe interessarti anche:  Modelli Transformer per il Forecasting delle Vendite: Guida Pratica con Codice NumPy e Calcolo del ROI

Cosa abbiamo imparato?

La covariata ha due funzioni distinte:

  • Spiegare variabilità — L’età contribuisce a spiegare la pressione, aumentando l'[math]R^2[/math].
  • Isolare l’associazione di interesse — Il coefficiente del trattamento viene stimato tenendo conto dell’età, riducendo il bias.

Randomizzazione: le covariate sono inutili?

No. La randomizzazione protegge dal confondimento sistematico, ma in campioni finiti possono verificarsi sbilanciamenti casuali. Una covariata fortemente prognostica aumenta la precisione della stima dell’effetto del trattamento anche in studi randomizzati.


3. Esercizio 2 — ANCOVA con covariata ordinale

Il problema

Un ricercatore confronta tre metodi di insegnamento (A, B, C) per studiarne l’effetto sul punteggio d’esame. Raccoglie anche il livello di istruzione dei genitori: Basso, Medio, Alto.

La domanda: il metodo ha effetto sul punteggio dopo aver tenuto conto dell’istruzione genitoriale?

ANCOVA: un ponte tra ANOVA e regressione

L’ANCOVA (Analysis of Covariance) confronta i gruppi tenendo contemporaneamente conto di una o più covariate:

[math]\displaystyle \text{Punteggio}_i = \beta_0 + \beta_1 \text{Metodo}_i + \beta_2 \text{Istruzione}_i + \varepsilon_i[/math]

Simuliamo un dataset realistico

Generiamo 60 studenti (20 per gruppo):

import numpy as np
import pandas as pd
import statsmodels.api as sm
from statsmodels.formula.api import ols

np.random.seed(456)

righe = []
for metodo in ['A', 'B', 'C']:
    for _ in range(20):
        istruzione = np.random.choice([1, 2, 3], p=[0.3, 0.4, 0.3])
        effetto_metodo = {'A': 0, 'B': 3, 'C': 1.5}[metodo]
        punteggio = 50 + effetto_metodo + 4 * istruzione + np.random.normal(0, 3)
        righe.append({'metodo': metodo, 'istruzione': istruzione, 'punteggio': punteggio})

df2 = pd.DataFrame(righe)

Codifica ordinale vs categorica

L’istruzione è ordinale. Possiamo codificarla come numerica (1, 2, 3), ma questa scelta assume che il passaggio da Basso a Medio sia equivalente a quello da Medio ad Alto. Verifichiamo se questa assunzione è sostenuta dai dati:

# Modello 1: istruzione come ordinale (lineare)
model_ord = ols("punteggio ~ C(metodo) + istruzione", data=df2).fit()

# Modello 2: istruzione come categorica
model_cat = ols("punteggio ~ C(metodo) + C(istruzione)", data=df2).fit()

print(f"AIC ordinale: {model_ord.aic:.1f}")
print(f"AIC categorico: {model_cat.aic:.1f}")

Output:

AIC ordinale: 298.0
AIC categorico: 299.9

L’AIC più basso del modello ordinale suggerisce che l’assunzione di linearità è ragionevole, ma la differenza è modesta. In un articolo scientifico converrebbe riportare entrambi i modelli o giustificare la scelta con ragionamento sostanziale.

Verifica dell’assunzione delle pendenze parallele

L’ANCOVA assume che l’effetto della covariata sia lo stesso in tutti i gruppi. Testiamo l’interazione:

model_int = ols("punteggio ~ C(metodo) * istruzione", data=df2).fit()
print(sm.stats.anova_lm(model_int, typ=2))

Output:

                          sum_sq    df         F    PR(>F)
C(metodo)             202.368     2.0  12.602  3.22e-05
istruzione            508.098     1.0  63.282  1.17e-10
C(metodo):istruzione    7.485     2.0   0.466     0.630
Residual              433.572    54.0     NaN       NaN

L’interazione non è significativa ([math]p = 0.630[/math]): le pendenze sono parallele e l’ANCOVA è appropriata.

Stima e confronti post-hoc

# Tabella ANOVA
anova_table = sm.stats.anova_lm(model_ord, typ=2)
print(anova_table)

Output:

               sum_sq    df          F        PR(>F)
C(metodo)    202.368   2.0  12.602119  3.224215e-05
istruzione   508.098   1.0  63.282020  1.166003e-10
Residual     433.572  54.0        NaN           NaN

Il metodo di insegnamento rimane significativo dopo aver aggiustato per l’istruzione.

Estimated Marginal Means (EMM)

Le medie grezze non sono il confronto più informativo. Calcoliamo le medie marginali stimate fissando la covariata al livello medio ([math]\text{istruzione} = 2[/math]):

pred = model_ord.predict(pd.DataFrame({
    "metodo": ["A", "B", "C"],
    "istruzione": [2, 2, 2]
}))

for metodo, valore in zip(["A", "B", "C"], pred):
    print(f"Metodo {metodo}: {valore:.2f}")

Output:

Metodo A: 57.63
Metodo B: 62.08
Metodo C: 59.19

Confronti post-hoc corretti

Non usare Tukey sulle medie grezze: i confronti devono essere coerenti con il modello.

from statsmodels.stats.multitest import multipletests
import numpy as np

contrasts = np.array([
    [0, 1, 0, 0],   # B - A
    [0, 0, 1, 0],   # C - A
    [0, 1, -1, 0]   # B - C
])

test = model_ord.t_test(contrasts)
p_values = np.asarray(test.pvalue).ravel()
reject, p_adjusted, _, _ = multipletests(p_values, method="holm")

print(test)
print("p-value corretti:", p_adjusted)

Output:

p-value corretti: [1.82e-05, 8.40e-02, 3.93e-03]

Dopo l’aggiustamento per l’istruzione e la correzione di Holm: B > A ([math]p_{\text{adj}} < 0.001[/math]), B > C ([math]p_{\text{adj}} = 0.004[/math]), mentre C vs A non è significativo ([math]p_{\text{adj}} = 0.084[/math]).


4. Esercizio 3 — Covariata time-varying in uno studio longitudinale

Il problema

Studio clinico di 12 mesi su 200 pazienti con diabete di tipo 2. Ogni paziente è osservato a 0, 3, 6, 9, 12 mesi. Misuriamo:

  • HbA1c (outcome)
  • BMI (covariata che cambia nel tempo)
  • tempo
  • trattamento (fisso nel tempo)

Perché la regressione lineare standard non basta

Le 1000 righe del dataset non sono indipendenti: 5 osservazioni appartengono allo stesso paziente. Questa dipendenza gerarchica viola un’assunzione fondamentale dell’OLS.

Simulazione del dataset longitudinale

import numpy as np
import pandas as pd

np.random.seed(123)

n_pazienti = 200
tempi = np.array([0, 3, 6, 9, 12])
righe = []

for paziente in range(n_pazienti):
    trattamento = np.random.binomial(1, 0.5)
    bmi_base = np.random.normal(29, 3)
    effetto_individuale = np.random.normal(0, 0.6)  # intercetta casuale
    slope_individuale = np.random.normal(0, 0.03)   # pendenza casuale

    for tempo in tempi:
        bmi = bmi_base - 0.10 * tempo + np.random.normal(0, 0.35)
        hba1c = (
            8.0
            + effetto_individuale
            + slope_individuale * tempo
            - 0.08 * tempo
            - 0.45 * trattamento
            + 0.12 * (bmi - 29)
            + np.random.normal(0, 0.25)
        )
        righe.append({
            "paziente": paziente, "tempo": tempo,
            "trattamento": trattamento, "bmi": bmi, "hba1c": hba1c
        })

df_long = pd.DataFrame(righe)

Linear Mixed Model

from statsmodels.regression.mixed_linear_model import MixedLM

model_full = MixedLM.from_formula(
    "hba1c ~ trattamento + tempo + bmi",
    groups="paziente",
    re_formula="~tempo",   # intercetta + pendenza casuali
    data=df_long
)
result_full = model_full.fit()
print(result_full.summary())

Output:

                     Coef.  Std.Err.    z    P>|z| [0.025 0.975]
----------------------------------------------------------------
Intercept             4.322    0.384  11.255 0.000  3.569  5.074
trattamento          -0.473    0.086  -5.513 0.000 -0.642 -0.305
tempo                -0.076    0.003 -25.111 0.000 -0.082 -0.070
bmi                   0.128    0.013   9.953 0.000  0.103  0.153
paziente Var          0.323    0.169
paziente x tempo Cov  0.001    0.007
tempo Var             0.001    0.001

Attenzione al warning di convergenza

statsmodels emette un ConvergenceWarning: The MLE may be on the boundary of the parameter space. Questo accade perché la varianza della pendenza temporale (tempo Var ≈ 0.001) è praticamente zero. In altre parole, le traiettorie individuali non differiscono molto nella loro velocità di cambiamento.

Forse potrebbe interessarti anche:  Matrici Python per la Gestione Aziendale: Guida Completa con 8 Esercizi Pratici e Applicazioni Avanzate

Verifichiamo se un modello più semplice (solo intercetta casuale) è sufficiente:

model_int_only = MixedLM.from_formula(
    "hba1c ~ trattamento + tempo + bmi",
    groups="paziente",
    re_formula="~1",   # solo intercetta casuale
    data=df_long
)
result_int_only = model_int_only.fit()
print(f"Log-Likelihood full: {result_full.llf:.1f}")
print(f"Log-Likelihood int-only: {result_int_only.llf:.1f}")

Output:

Log-Likelihood full: -448.4
Log-Likelihood int-only: -482.7

Il modello full ha una log-likelihood nettamente superiore, quindi la struttura a intercetta e pendenza casuali è giustificata nonostante la varianza sul boundary. In un’analisi reale, si potrebbe anche considerare un modello con solo intercetta casuale se il guadagno in log-likelihood non compensasse la complessità aggiuntiva.

ICC: quanto conta la struttura gerarchica?

L’Intraclass Correlation Coefficient (ICC) misura la quota di variabilità dovuta alle differenze tra pazienti:

var_paziente = result_int_only.cov_re.iloc[0, 0]
var_residuo = result_int_only.scale
icc = var_paziente / (var_paziente + var_residuo)
print(f"ICC = {icc:.3f}")

Output:

ICC = 0.819

Un ICC dell’82% significa che l’82% della variabilità totale è spiegata dalle differenze tra pazienti. Ignorare questa struttura gerarchica sarebbe un errore grave: una regressione OLS sottostimerebbe gli errori standard e produrrebbe inferenze distorte.

Interpretazione degli effetti fissi

  • Trattamento: [math]\hat{\beta} = -0.473[/math], [math]p < 0.001[/math]. A parità di tempo e BMI, il trattamento riduce l’HbA1c di circa 0.47 punti.
  • Tempo: [math]\hat{\beta} = -0.076[/math] al mese, [math]p < 0.001[/math]. Tendenza lineare alla riduzione.
  • BMI: [math]\hat{\beta} = 0.128[/math], [math]p < 0.001[/math]. Vicinissimo al vero valore generativo (0.12).

Decomposizione within/between

Una covariata time-varying contiene due informazioni distinte:

  • Between-person: i pazienti con BMI medio più alto hanno HbA1c più alta?
  • Within-person: quando un paziente aumenta il proprio BMI rispetto alla sua media, aumenta anche la sua HbA1c?

Decomponiamo il BMI:

df_long["bmi_mean"] = df_long.groupby("paziente")["bmi"].transform("mean")
df_long["bmi_within"] = df_long["bmi"] - df_long["bmi_mean"]

model_decomp = MixedLM.from_formula(
    "hba1c ~ trattamento + tempo + bmi_mean + bmi_within",
    groups="paziente",
    re_formula="~1",
    data=df_long
)
result_decomp = model_decomp.fit()
print(result_decomp.summary())

Output:

             Coef.  Std.Err.    z    P>|z| [0.025 0.975]
--------------------------------------------------------
bmi_mean      0.124    0.015   8.285 0.000  0.095  0.154
bmi_within    0.136    0.029   4.651 0.000  0.079  0.193

Entrambi gli effetti sono significativi e coerenti con il vero meccanismo generativo. Questa decomposizione è molto più informativa di un singolo coefficiente del BMI.


5. Errori frequenti nell’uso delle covariate

Errore Descrizione Soluzione
Confondere covariata e confondente Pensare che siano sinonimi Ricorda: covariata = variabile nel modello; confondente = concetto causale
Codifica ordinale senza riflettere Basso=1, Medio=2, Alto=3 assume linearità Verifica con modello categorico e confronta AIC
Correlazione ≠ controllo causale Inserire una variabile non elimina automaticamente il bias Ragiona sulla struttura causale (DAG)
Ignorare le interazioni ANCOVA assume pendenze parallele Testa sempre metodo × covariata
Post-hoc sulle medie grezze Tukey sui dati grezzi ≠ confronti aggiustati Effettua i contrasti sul modello stimato
Trattare dati longitudinali come indipendenti OLS su misure ripetute viola le assunzioni Usa Mixed Models e calcola l’ICC
Boundary warning ignorato Varianza casuale ≈ 0 senza verifica Confronta modelli nested con log-likelihood o test del rapporto di verosimiglianza

6. Covariate e causal inference

Un errore frequente è pensare: “Più covariate inserisco, meglio è.”

In un modello predittivo questo può essere ragionevole. In un’analisi causale, controllare per una variabile che è conseguenza del trattamento (un mediatore) può introdurre distorsioni.

Esempio:

Trattamento → BMI → Outcome

Qui il BMI è un mediatore. Inserirlo come covariata “blocca” parte del percorso causale e sottostima l’effetto totale del trattamento.

Regola pratica: prima di inserire una covariata, chiediti:

  • È misurata prima del trattamento?
  • È associata sia al trattamento sia all’outcome?
  • È un confondente o un mediatore?
  • È una collider (causa comune di due variabili già incluse)?

Un DAG (Directed Acyclic Graph) aiuta a visualizzare queste relazioni.


7. Quale modello scegliere?

Struttura dati Modello Covariata Effetto casuale
1 osservazione per soggetto OLS / Regressione lineare Continua, ordinale, categorica No
Confronto tra gruppi + covariata ANCOVA / Regressione Continua o ordinale No
Covariata ordinale Regressione con codifica appropriata Ordinale (testa linearità) No
Covariata categoriale Variabili dummy / C(variabile) Categorica No
Misure ripetute, covariata fissa Mixed Model Continua Intercetta
Misure ripetute, covariata time-varying Mixed Model Continua (decomposta) Intercetta ± Pendenza
Interesse per effetti within/between Mixed Model + decomposizione Media + deviazione Intercetta
Effetto diverso tra gruppi Modello con interazione Qualsiasi A seconda dei dati
Forse potrebbe interessarti anche:  SQL per Colloqui Tecnici: 20 Query Esistenziali con Dataset, Esercizi e Soluzioni per Developer e Data Analyst

La domanda non è “quale funzione Python uso?” ma “qual è la struttura dei miei dati e quale domanda voglio rispondere?”


Commento agli Esercizi 

Esercizio 1 (Omitted Variable Bias): L’arte di simulare il bias

Molti tutorial sull’OVB si limitano a mostrare equazioni matematiche. In questo script, abbiamo costruito il bias “a tavolino”: la riga [math]\text{prob\_tratt} = 0.2 + 0.6 \cdot (\text{eta} – 50) / 30[/math] è il cuore del problema. Simula esattamente ciò che accade in un setting osservazionale reale (es. i medici prescrivono il farmaco più frequentemente a chi è più anziano). Vedere il coefficiente passare da [math]13.41[/math] a [math]10.20[/math] dimostra visivamente come l’inclusione della covariata purifichi la stima isolando l’effetto reale, agendo come una sorta di filtro per il confondimento.


Esercizio 2 (ANCOVA): Oltre il p-value, il rigore dei contrasti

La vera chicca qui non è tanto la chiamata a anova_lm, ma il blocco sui confronti post-hoc. Troppo spesso i data scientist usano un test di Tukey sulle medie grezze del dataset, dimenticando che se il modello aggiusta per una covariata, anche i confronti a coppie devono farlo. L’utilizzo di una matrice di contrasti custom ([math][0, 1, 0, 0][/math], ecc.) passata direttamente ai coefficienti stimati dal modello è la procedura rigorosa e professionalmente ineccepibile per testare differenze tra gruppi mantenendo ferma la covariata.


Esercizio 3 (Mixed Models): Rompere l’illusione della media

Questo è l’esercizio con il maggior valore applicativo. Nel mondo reale, le covariate quasi mai sono statiche. Il passaggio in cui la variabile BMI viene esplosa in bmi_mean e bmi_within è una tecnica avanzatissima. Permette di rispondere a due domande di business/cliniche totalmente diverse nella stessa riga di codice: “Le persone più in sovrappeso hanno valori di HbA1c peggiori?” (effetto between) e “Se un paziente specifico prende peso rispetto alla sua media storica, il suo HbA1c peggiora?” (effetto within). Separare questi effetti evita la cosiddetta Fallacia Ecologica, un errore fatale in cui incappano moltissime analisi regressive standard.


8. Checklist per l’analisi

Prima di inserire una covariata nel modello, verifica:

  • [ ] Qual è la mia variabile risposta?
  • [ ] Qual è l’effetto che voglio stimare?
  • [ ] La covariata è misurata prima del trattamento?
  • [ ] È continua, nominale o ordinale?
  • [ ] La relazione con l’outcome è plausibilmente lineare?
  • [ ] L’effetto della covariata può cambiare tra i gruppi? (testa l’interazione)
  • [ ] La covariata cambia nel tempo?
  • [ ] Le osservazioni sono indipendenti o annidate?
  • [ ] Ci sono dati mancanti? (MCAR, MAR, MNAR?)
  • [ ] Sto facendo previsione o inferenza causale?

9. Conclusione

La covariata non è un “aggiustamento automatico” da inserire per ripulire i dati.

È una scelta statistica che modifica:

  • l’interpretazione dei coefficienti
  • la precisione delle stime
  • le assunzioni del modello
  • in alcuni casi, la domanda causale stessa

Con Python possiamo partire da una semplice regressione:

[math]\displaystyle Y_i = \beta_0 + \beta_1 X_i + \varepsilon_i[/math]

e arrivare a modelli sofisticati:

[math]\displaystyle Y_{it} = \beta X_{it} + b_{0i} + b_{1i} \text{Time}_{it} + \varepsilon_{it}[/math]

Ma il punto fondamentale non è memorizzare LinearRegression, ols o MixedLM.

È capire perché un certo modello è appropriato per una certa struttura dei dati.

Prima di inserire una covariata, fermati e chiediti:

che ruolo ha questa variabile nel processo che sto osservando?

Da questa domanda dipende molto più della semplice formula del modello.

📚 Per approfondire: ANOVA, test statistici e analisi della sopravvivenza

Se vuoi approfondire gli strumenti della statistica inferenziale e della Data Science, dalla scomposizione della varianza ai test d’ipotesi, fino alla causal inference e ai modelli di sopravvivenza, puoi consultare queste guide ed esercitazioni:

👉 Analisi della Varianza (ANOVA): guida completa con esercizi pratici e calcoli dettagliati

👉 ANOVA spiegata: 6 esercizi pratici per comprendere l’analisi della varianza con codice Python

👉 ANOVA spiegata con esercizi risolti: Customer Success, finanza e retail

👉 P-value: cos’è, come si calcola e quando si usa nei test statistici

👉 Esercizi ANOVA risolti: come spiegare l’analisi della varianza al management

👉 Tutorial CausalML – Parte 1: dalla teoria all’Uplift Modeling con Python

👉 Analisi della sopravvivenza e LTV: dalla curva di Kaplan-Meier al modello di Cox

 

Pubblicità