Test di Logrank in Python: Kaplan-Meier, survival analysis e confronto delle curve

Cerca:

Generic selectors
Exact matches only
Search in title
Search in content
Post Type Selectors

Quando analizziamo i dati di un trial clinico, il tempo diventa una variabile fondamentale.

Non basta sapere se un paziente è deceduto oppure no.

Dobbiamo sapere quando si è verificato l’evento.

La stessa logica compare in molti altri contesti:

  • tempo fino alla recidiva di una malattia;
  • tempo fino al guasto di un macchinario;
  • tempo fino all’abbandono di un servizio;
  • tempo fino al churn di un cliente;
  • tempo necessario affinché un utente completi un’azione;
  • durata di un trattamento prima della sua interruzione.

Questi problemi appartengono alla survival analysis, o analisi di sopravvivenza.

Una delle difficoltà principali è che non sempre osserviamo l’evento per tutti i soggetti. Alcuni pazienti possono abbandonare lo studio, altri possono essere ancora vivi alla fine del follow-up. Queste osservazioni sono censurate.

Il test di Logrank nasce proprio per confrontare due o più gruppi tenendo conto della dimensione temporale del problema e delle censure.

Ma c’è un punto fondamentale:

Il Logrank non confronta semplicemente quanti eventi si sono verificati nei due gruppi. Confronta come gli eventi si distribuiscono nel tempo, considerando chi era ancora a rischio in ciascun momento.

In questo articolo costruiremo il concetto passo dopo passo, attraverso esempi progressivi, e vedremo anche come passare dal calcolo manuale a Python.

Pubblicità

Perché non basta contare gli eventi?

Immaginiamo due trattamenti con 100 pazienti ciascuno.

Nel gruppo A osserviamo 30 decessi.

Nel gruppo B osserviamo 40 decessi.

Una prima analisi potrebbe essere:

“Il trattamento A sembra migliore perché ha meno decessi.”

Ma questa conclusione potrebbe essere completamente sbagliata.

Supponiamo infatti che:

  • nel gruppo A i 30 decessi si verifichino nei primi mesi;
  • nel gruppo B i 40 decessi si verifichino soprattutto alla fine del follow-up.

Il semplice conteggio finale non racconta la stessa storia che racconterebbe la distribuzione temporale degli eventi.

La survival analysis cerca quindi di rispondere a una domanda più informativa:

Qual è il rischio di osservare l’evento nel tempo e come differisce tra i gruppi?

La censura: quando non osserviamo l’evento

Supponiamo di seguire un paziente per 24 mesi.

Se il paziente muore al mese 15, osserviamo:

  • tempo = 15;
  • evento = 1.

Ma se al mese 24 il paziente è ancora vivo, non possiamo dire che il paziente “non morirà”.

Sappiamo soltanto che:

il paziente è sopravvissuto almeno 24 mesi.

Avremo quindi:

  • tempo = 24;
  • evento = 0.

Questa è una censura a destra.

La distinzione è fondamentale.

Evento

Il fenomeno che stiamo studiando si è verificato.

Censura

Non abbiamo osservato l’evento durante il periodo di osservazione.

La censura non significa quindi “nessun evento”.

Significa:

non sappiamo cosa sarebbe successo dopo il momento della censura.

Commento applicativo

Immaginiamo di analizzare il churn di un SaaS.

Un cliente entra a gennaio e rimane attivo fino a dicembre, quando termina il periodo di osservazione.

Non possiamo classificare quel cliente come “non churner”.

Possiamo soltanto affermare:

il cliente non ha effettuato churn durante i 12 mesi osservati.

Trattarlo come un cliente che non farà mai churn introdurrebbe un errore concettuale.


Kaplan-Meier: prima osserviamo le curve

Prima di applicare il Logrank è utile costruire le curve di Kaplan-Meier.

La funzione di sopravvivenza è:

[math]\displaystyle S(t) = P(T > t)[/math]

e rappresenta la probabilità stimata di non aver ancora osservato l’evento entro il tempo [math]t[/math].

La stima di Kaplan-Meier è:

[math]\displaystyle \hat S(t) = \prod_{t_i \le t} \left(1 – \frac{d_i}{n_i}\right)[/math]

dove:

  • [math]t_i[/math] è un tempo in cui si verifica almeno un evento;
  • [math]d_i[/math] è il numero di eventi a quel tempo;
  • [math]n_i[/math] è il numero di soggetti a rischio immediatamente prima di quel tempo.

Le osservazioni censurate non fanno scendere direttamente la curva, ma modificano il numero di soggetti ancora a rischio nei tempi successivi.


Che cos’è il test di Logrank?

Il Logrank è un test non parametrico utilizzato per confrontare le curve di sopravvivenza di due o più gruppi.

L’ipotesi nulla, nel caso di due gruppi, è:

[math]\displaystyle H_0: \text{nessuna differenza sistematica tra le curve di sopravvivenza}[/math]

L’alternativa è:

[math]\displaystyle H_1: \text{le curve differiscono}[/math]

Il principio è semplice.

Ad ogni tempo in cui si verifica un evento chiediamo:

Quanti eventi ci aspetteremmo nel gruppo A se le due popolazioni avessero lo stesso rischio?

Confrontiamo quindi:

[math]\displaystyle O_A[/math]

eventi osservati nel gruppo A con:

[math]\displaystyle E_A[/math]

eventi attesi nel gruppo A.

La differenza viene accumulata lungo tutto il follow-up.


Il concetto fondamentale: il risk set

Supponiamo che al tempo [math]t[/math]:

  • [math]n_A[/math] soggetti siano ancora a rischio nel gruppo A;
  • [math]n_B[/math] siano ancora a rischio nel gruppo B;
  • [math]d[/math] siano gli eventi totali.

Sotto [math]H_0[/math], l’evento dovrebbe essere distribuito proporzionalmente alla numerosità dei gruppi ancora a rischio.

L’evento atteso nel gruppo A è:

[math]\displaystyle E_A = \frac{n_A}{n_A + n_B} d[/math]

Questo passaggio è il cuore del Logrank.

Non utilizziamo quindi la numerosità iniziale.

Utilizziamo:

la numerosità dei soggetti ancora a rischio in quel momento.

Un esempio 

Supponiamo che al mese 10 siano ancora a rischio:

  • 80 pazienti nel gruppo A;
  • 40 pazienti nel gruppo B.

In quel momento si verifica un evento.

Il totale a rischio è:

[math]\displaystyle 80 + 40 = 120[/math]

La probabilità che, sotto [math]H_0[/math], l’evento appartenga al gruppo A è:

[math]\displaystyle \frac{80}{120} = \frac{2}{3}[/math]

Quindi l’evento atteso per A è:

[math]\displaystyle E_A = \frac{2}{3}[/math]

Se osserviamo invece l’evento nel gruppo B:

[math]\displaystyle O_A = 0[/math]

e quindi:

[math]\displaystyle O_A – E_A = -\frac{2}{3}[/math]

Ripetiamo il procedimento per tutti i tempi di evento.

È la somma di queste differenze che costituisce l’informazione utilizzata dal test.


La statistica del Logrank

Nel caso di due gruppi, la statistica può essere espressa come:

[math]\displaystyle \chi^2 = \frac{(O_A – E_A)^2}{V_A}[/math]

dove [math]V_A[/math] è la varianza della differenza tra eventi osservati e attesi sotto [math]H_0[/math].

Per un singolo tempo:

[math]\displaystyle V_i = \frac{n_{Ai} n_{Bi} d_i (n_i – d_i)}{n_i^2 (n_i – 1)}[/math]

con:

[math]\displaystyle n_i = n_{Ai} + n_{Bi}[/math]

La varianza complessiva è:

[math]\displaystyle V = \sum_i V_i[/math]

e quindi:

[math]\displaystyle \chi^2 = \frac{(O_A – E_A)^2}{V}[/math]

Per due gruppi, la statistica segue approssimativamente una distribuzione [math]\chi^2[/math] con un grado di libertà.


Esercizio 1 — Perché una tabella 2×2 non è un Logrank

Consideriamo 100 pazienti:

Gruppo Deceduti Sopravvissuti
A 15 35
B 22 28

Potremmo costruire una tabella 2×2 e applicare un test [math]\chi^2[/math].

Gli eventi attesi nel gruppo A sarebbero:

[math]\displaystyle E_A = \frac{50 \times 37}{100} = 18.5[/math]

La statistica [math]\chi^2[/math] sarebbe:

[math]\displaystyle \chi^2 = \frac{(15 – 18.5)^2}{18.5} + \frac{(22 – 18.5)^2}{18.5}[/math]

ottenendo:

[math]\displaystyle \chi^2 \approx 1.324[/math]

Il risultato non è significativo a [math]\alpha = 0.05[/math].

Ma attenzione

Questo non è un test di Logrank.

È un test sulle proporzioni finali.

Mancano infatti i tempi degli eventi.

Non sappiamo se i 15 decessi di A siano avvenuti:

  • tutti nei primi mesi;
  • tutti alla fine;
  • oppure distribuiti uniformemente.

Il Logrank avrebbe bisogno proprio di questa informazione.

Commento applicativo

Questa distinzione è fondamentale.

Se abbiamo soltanto:

evento sì/no alla fine dello studio

possiamo utilizzare metodi per dati binari.

Se abbiamo:

tempo + evento/censura

entriamo nel dominio della survival analysis.

Non bisogna trasformare automaticamente un problema di sopravvivenza in una tabella 2×2.


Esercizio 2 — Logrank con dati censurati

Passiamo ora a un esempio completo in cui sono presenti anche osservazioni censurate.

Consideriamo due gruppi di pazienti, F e S, seguiti nel tempo.

Nel gruppo F abbiamo:

[math]\displaystyle 3, 6, 8, 10^+, 12, 14, 15^+, 18, 20, 22, 24^+, 26, 28, 30^+, 32, 34, 36, 38^+, 40, 42[/math]

Nel gruppo S abbiamo:

[math]\displaystyle 2, 4, 6^+, 8, 10, 12^+, 14, 16, 18^+, 20, 22, 24, 26^+, 28, 30, 32^+, 34, 36, 38, 40^+[/math]

Il simbolo (+) indica una censura a destra.

Abbiamo quindi:

  • gruppo F: 15 eventi e 5 censure;
  • gruppo S: 14 eventi e 6 censure;
  • 20 soggetti iniziali per ciascun gruppo.

L’obiettivo è verificare se le due popolazioni presentano curve di sopravvivenza significativamente differenti.


Passo 1 — Perché dobbiamo costruire i risk set?

Il Logrank non utilizza semplicemente il numero iniziale di pazienti.

A ogni tempo in cui si verifica almeno un evento dobbiamo sapere:

  • quanti soggetti del gruppo F sono ancora a rischio;
  • quanti soggetti del gruppo S sono ancora a rischio;
  • quanti eventi si verificano in F;
  • quanti eventi si verificano in S.

Questo è necessario perché, sotto l’ipotesi nulla, l’evento viene distribuito tra i gruppi in funzione di quanti soggetti sono ancora a rischio in quel momento.

L’evento atteso nel gruppo F è:

[math]\displaystyle E_{Fi} = \frac{n_{Fi}}{n_i} d_i[/math]

dove:

[math]\displaystyle n_i = n_{Fi} + n_{Si}[/math]

e [math]d_i[/math] è il numero totale di eventi al tempo [math]i[/math].


Passo 2 — Costruiamo la tabella dei risk set

Per evitare di perdere informazioni, riportiamo esplicitamente tutti i tempi in cui si verifica almeno un evento.

Tempo F a rischio S a rischio Eventi F Eventi S Eventi totali Atteso F
2 20 20 0 1 1 0,500
3 20 19 1 0 1 0,513
4 19 19 0 1 1 0,500
6 19 18 1 0 1 0,514
8 18 17 1 1 2 1,029
10 17 16 0 1 1 0,515
12 16 15 1 0 1 0,516
14 15 14 1 1 2 1,034
16 13 13 0 1 1 0,500
18 13 12 1 0 1 0,520
20 12 11 1 1 2 1,043
22 11 10 1 1 2 1,048
24 10 9 0 1 1 0,526
26 9 8 1 0 1 0,529
28 8 7 1 1 2 1,067
30 7 6 0 1 1 0,538
32 6 5 1 0 1 0,545
34 5 4 1 1 2 1,111
36 4 3 1 1 2 1,143
38 3 2 0 1 1 0,600
40 2 1 1 0 1 0,667
42 1 0 1 0 1 1,000

Questa tabella contiene il cuore del calcolo del Logrank.

Un controllo importante sui dati censurati

Notiamo, per esempio, cosa succede tra il tempo 14 e il tempo 16.

Al tempo 14 sono ancora a rischio:

[math]\displaystyle n_F = 15, \qquad n_S = 14[/math]

Forse potrebbe interessarti anche:  Python per il Controllo di Gestione: Analisi Avanzata della Marginalità Retail con Pandas

Al tempo 15 si verifica una censura nel gruppo F.

La censura non è un evento e quindi non fa diminuire direttamente la curva di sopravvivenza.

Tuttavia, il soggetto censurato non deve più essere considerato a rischio nei tempi successivi.

Per questo al tempo 16 troviamo:

[math]\displaystyle n_F = 13, \qquad n_S = 13[/math]

e non 14 soggetti a rischio nel gruppo F.

Questo esempio mostra concretamente perché la gestione delle censure è fondamentale.


Passo 3 — Calcoliamo alcuni eventi attesi

Vediamo nel dettaglio i primi tempi.

Tempo 2

Abbiamo:

[math]\displaystyle n_F = 20, \qquad n_S = 20, \qquad d = 1[/math]

L’evento si verifica nel gruppo S.

Sotto [math]H_0[/math], l’evento atteso in F è:

[math]\displaystyle E_F = \frac{20}{40} \cdot 1 = 0,5[/math]

Tempo 3

Dopo l’evento verificatosi nel gruppo S al tempo 2:

[math]\displaystyle n_F = 20, \qquad n_S = 19[/math]

L’evento si verifica in F.

Quindi:

[math]\displaystyle E_F = \frac{20}{39} \approx 0,513[/math]

L’evento osservato in F è 1, mentre quello atteso è circa 0,513.

Il contributo alla differenza osservato-atteso è quindi:

[math]\displaystyle 1 – 0,513 \approx 0,487[/math]

Tempo 8

Al tempo 8 si verifica un evento in entrambi i gruppi.

Abbiamo:

[math]\displaystyle n_F = 18, \qquad n_S = 17[/math]

e:

[math]\displaystyle d = 2[/math]

Quindi:

[math]\displaystyle E_F = \frac{18}{35} \cdot 2 \approx 1,029[/math]

Qui il gruppo F osserva un evento, ma sotto [math]H_0[/math] ci aspetteremmo circa 1,029 eventi.

Il contributo di questo tempo è quindi:

[math]\displaystyle 1 – 1,029 \approx -0,029[/math]

Questo esempio mostra anche come il Logrank gestisca correttamente i tempi con più eventi contemporaneamente.


Passo 4 — Sommiamo gli eventi osservati e attesi

Nel gruppo F abbiamo complessivamente:

[math]\displaystyle O_F = 15[/math]

eventi osservati.

Sommando tutti gli eventi attesi riportati nella tabella otteniamo:

[math]\displaystyle E_F \approx 15,959[/math]

quindi:

[math]\displaystyle 15 – 15,959 \approx -0,959[/math]

Il gruppo F presenta quindi leggermente meno eventi di quelli che ci aspetteremmo sotto l’ipotesi nulla.

Ma questa differenza, da sola, non è sufficiente.

Dobbiamo rapportarla alla sua variabilità.


Passo 5 — Calcoliamo la varianza

Per ogni tempo di evento utilizziamo:

[math]\displaystyle V_i = \frac{n_{Fi} n_{Si} d_i (n_i – d_i)}{n_i^2 (n_i – 1)}[/math]

dove:

[math]\displaystyle n_i = n_{Fi} + n_{Si}[/math]

La varianza complessiva è:

[math]\displaystyle V = \sum_i V_i[/math]

Nel nostro caso otteniamo:

[math]\displaystyle V \approx 6,675[/math]


Passo 6 — Calcoliamo la statistica del Logrank

La statistica per due gruppi è:

[math]\displaystyle \chi^2 = \frac{(O_F – E_F)^2}{V}[/math]

Sostituendo i valori:

[math]\displaystyle \chi^2 = \frac{(15 – 15,959)^2}{6,675}[/math]

e quindi:

[math]\displaystyle \boxed{\chi^2 \approx 0,138}[/math]

Per un confronto tra due gruppi abbiamo:

[math]\displaystyle df = 1[/math]

Il valore critico della distribuzione [math]\chi^2_1[/math] al livello:

[math]\displaystyle \alpha = 0,05[/math]

è circa:

[math]\displaystyle 3,841[/math]

Poiché:

[math]\displaystyle 0,138 < 3,841[/math]

non rifiutiamo l’ipotesi nulla.

Conclusione

Non abbiamo evidenza statistica sufficiente per affermare che le due curve di sopravvivenza siano differenti.

È importante però formulare correttamente la conclusione.

Non dobbiamo dire:

“I due trattamenti sono uguali.”

Dobbiamo dire:

Con questi dati non abbiamo evidenza sufficiente per rifiutare l’ipotesi di uguaglianza delle curve di sopravvivenza.

La distinzione è fondamentale: un risultato non significativo non dimostra l’assenza di un effetto.

Cosa abbiamo imparato da questo esercizio?

Questo esempio mostra quattro aspetti fondamentali del Logrank:

  1. gli eventi devono essere ordinati nel tempo;
  2. il numero di soggetti a rischio cambia continuamente;
  3. le censure modificano i risk set successivi senza essere conteggiate come eventi;
  4. gli eventi osservati devono essere confrontati con quelli attesi sotto l’ipotesi nulla.

Il punto centrale è quindi:

[math]\displaystyle \text{eventi osservati} \quad \text{vs} \quad \text{eventi attesi}[/math]

ma con una precisazione fondamentale: questo confronto viene costruito tempo per tempo, utilizzando i soggetti che sono ancora a rischio.

Pubblicità

Logrank e assunzione di proportional hazards

A questo punto è importante correggere un equivoco frequente.

Il Logrank non richiede che l’hazard sia costante nel tempo.

L’assunzione di proportional hazards riguarda invece il rapporto tra gli hazard dei gruppi:

[math]\displaystyle HR(t) = \frac{h_A(t)}{h_B(t)}[/math]

Se:

[math]\displaystyle HR(t) = HR[/math]

indipendentemente da [math]t[/math], abbiamo proportional hazards.

Gli hazard possono comunque aumentare o diminuire nel tempo.

Perché è importante?

Il Logrank è particolarmente efficiente quando le differenze tra i gruppi sono coerenti nel tempo.

Se invece:

  • le curve si incrociano;
  • il beneficio compare molto tardi;
  • il trattamento ha effetti iniziali e tardivi molto diversi;

il Logrank standard può perdere potenza o produrre un risultato globale difficile da interpretare.


Come verificare la proportional hazards

Non esiste un singolo controllo sufficiente.

Possiamo utilizzare:

1. Ispezione grafica

Osserviamo le curve di Kaplan-Meier.

Curve che si incrociano possono essere un segnale di non-proporzionalità.

2. Grafici log(-log)

I grafici delle trasformazioni:

[math]\displaystyle \log[-\log S(t)][/math]

possono fornire indicazioni sulla proportional hazards.

3. Residui di Schoenfeld

Nel modello di Cox possiamo utilizzare i residui di Schoenfeld per verificare se l’effetto delle covariate cambia nel tempo.

4. Analisi dell’effetto nel tempo

Possiamo stimare effetti separati in intervalli temporali diversi.


Esercizio 3 — Tre gruppi e stratificazione

Supponiamo di confrontare tre trattamenti:

  • Gruppo 1: terapia standard;
  • Gruppo 2: terapia + anticorpo monoclonale;
  • Gruppo 3: terapia + immunoterapia.

I pazienti sono inoltre classificati per stadio della malattia:

  • I-II;
  • III-IV.

Il problema è che lo stadio può essere associato sia alla sopravvivenza sia alla scelta o all’effetto del trattamento.

Per evitare che questa variabile distorca il confronto, possiamo utilizzare un Logrank stratificato.

Passo 1 — Costruiamo i risk set all’interno di ciascuno strato

Non confrontiamo semplicemente:

[math]\displaystyle O_1, O_2, O_3[/math]

sull’intero campione.

Costruiamo invece i confronti separatamente per:

  • strato I-II;
  • strato III-IV.

All’interno di ogni strato calcoliamo:

[math]\displaystyle O_{gj}[/math]

e:

[math]\displaystyle E_{gj}[/math]

per ciascun gruppo [math]g[/math].

Passo 2 — Sommiamo le informazioni degli strati

In forma matriciale, il test stratificato utilizza:

[math]\displaystyle \mathbf{O} – \mathbf{E}[/math]

e la matrice di covarianza:

[math]\displaystyle \mathbf{V}[/math]

La statistica è:

[math]\displaystyle \chi^2 = (\mathbf O – \mathbf E)^T \mathbf V^{-1} (\mathbf O – \mathbf E)[/math]

Nel caso di tre gruppi, i gradi di libertà sono:

[math]\displaystyle 3 – 1 = 2[/math]

Commento applicativo

La stratificazione è utile quando vogliamo controllare una variabile che influenza il rischio di base ma non è necessariamente il nostro oggetto principale di studio.

Un esempio tipico è:

confronto di trattamenti stratificando per centro clinico.

Oppure:

confronto di churn stratificando per segmento di cliente.

Attenzione

Non possiamo calcolare correttamente un vero Logrank stratificato avendo soltanto il numero finale di eventi per strato.

Servono i tempi degli eventi e i risk set.

Questo è un punto metodologico da non sacrificare per ottenere un esercizio numericamente semplice.


Esercizio 4 — Calcolo manuale guidato del Logrank

Dopo aver visto un esempio con dati censurati, consideriamo ora un caso più semplice per concentrarci sul calcolo manuale del Logrank.

Abbiamo due gruppi:

Trattamento T

[math]\displaystyle 5, 10, 12, 15, 18, 20, 22, 25, 28, 30[/math]

Controllo C

[math]\displaystyle 3, 7, 11, 14, 16, 17, 21, 24, 26, 29[/math]

Tutti i pazienti hanno osservato l’evento.

Quindi:

  • 10 pazienti nel gruppo T;
  • 10 pazienti nel gruppo C;
  • 20 eventi complessivi;
  • nessuna censura.

L’assenza di censure rende l’esempio più semplice, ma il principio del Logrank rimane esattamente lo stesso.


Passo 1 — Ordiniamo tutti gli eventi

Unendo i due gruppi e ordinando i tempi otteniamo:

[math]\displaystyle 3, 5, 7, 10, 11, 12, 14, 15, 16, 17, 18, 20, 21, 22, 24, 25, 26, 28, 29, 30[/math]

A ogni tempo dobbiamo aggiornare il risk set.

Per esempio, al giorno 3 tutti i 20 pazienti sono ancora a rischio:

[math]\displaystyle n_T = 10, \qquad n_C = 10[/math]

L’evento avviene nel gruppo C.

Al giorno 5, il paziente del gruppo C che ha avuto l’evento al giorno 3 non è più a rischio:

[math]\displaystyle n_T = 10, \qquad n_C = 9[/math]

L’evento avviene questa volta nel gruppo T.

E così via.


Passo 2 — Costruiamo la tabella completa

Tempo T a rischio C a rischio Eventi T Eventi C Eventi totali Atteso T
3 10 10 0 1 1 0,500
5 10 9 1 0 1 0,526
7 9 9 0 1 1 0,500
10 9 8 1 0 1 0,529
11 8 8 0 1 1 0,500
12 8 7 1 0 1 0,533
14 7 7 0 1 1 0,500
15 7 6 1 0 1 0,538
16 6 6 0 1 1 0,500
17 6 5 0 1 1 0,545
18 6 4 1 0 1 0,600
20 5 4 1 0 1 0,556
21 4 4 0 1 1 0,500
22 4 3 1 0 1 0,571
24 3 3 0 1 1 0,500
25 3 2 1 0 1 0,600
26 2 2 0 1 1 0,500
28 2 1 1 0 1 0,667
29 1 1 0 1 1 0,500
30 1 0 1 0 1 1,000

La colonna più importante è Atteso T.

È il numero medio di eventi che ci aspetteremmo nel gruppo T se, in quel momento, i due gruppi avessero lo stesso rischio.


Passo 3 — Vediamo nel dettaglio i primi due eventi

Giorno 3

All’inizio abbiamo:

[math]\displaystyle n_T = 10, \qquad n_C = 10[/math]

quindi:

[math]\displaystyle n = 20[/math]

Si verifica un evento nel gruppo C:

[math]\displaystyle d_T = 0, \qquad d_C = 1[/math]

Sotto [math]H_0[/math], l’evento dovrebbe essere distribuito proporzionalmente ai soggetti a rischio.

L’atteso per T è:

[math]\displaystyle E_T = \frac{10}{20} \cdot 1 = 0,5[/math]

L’evento osservato in T è:

[math]\displaystyle O_T = 0[/math]

Quindi il contributo osservato-atteso è:

[math]\displaystyle 0 – 0,5 = -0,5[/math]

Giorno 5

Dopo l’evento del giorno 3, rimangono:

[math]\displaystyle n_T = 10, \qquad n_C = 9[/math]

quindi:

[math]\displaystyle n = 19[/math]

L’evento si verifica nel gruppo T.

L’evento atteso per T è:

[math]\displaystyle E_T = \frac{10}{19} \approx 0,526[/math]

L’evento osservato è:

[math]\displaystyle O_T = 1[/math]

e quindi:

[math]\displaystyle 1 – 0,526 = 0,474[/math]

Notiamo una cosa importante: il gruppo T ha avuto un evento, ma non possiamo semplicemente dire che “l’evento è a suo sfavore”.

Dobbiamo confrontare quell’evento con ciò che ci saremmo aspettati dato il numero di soggetti ancora a rischio nei due gruppi.


Passo 4 — Continuiamo il procedimento

Il calcolo viene ripetuto per tutti i 20 tempi di evento.

Per esempio, al giorno 18:

[math]\displaystyle n_T = 6, \qquad n_C = 4[/math]

e l’evento si verifica in T.

Quindi:

[math]\displaystyle E_T = \frac{6}{10} = 0,6[/math]

e:

[math]\displaystyle 1 – 0,6 = 0,4[/math]

Al giorno 28, invece:

[math]\displaystyle n_T = 2, \qquad n_C = 1[/math]

e l’evento è nuovamente in T.

Forse potrebbe interessarti anche:  Funzione Softmax nel Machine Learning: formula, stabilità numerica e applicazioni in Python e PyTorch

L’atteso è:

[math]\displaystyle E_T = \frac{2}{3} \approx 0,667[/math]

Quindi:

[math]\displaystyle 1 – 0,667 = 0,333[/math]

L’ultimo evento, al giorno 30, è ancora in T.

A quel punto rimane un solo soggetto a rischio:

[math]\displaystyle n_T = 1, \qquad n_C = 0[/math]

e quindi:

[math]\displaystyle E_T = 1[/math]

L’evento osservato e quello atteso coincidono.


Passo 5 — Sommiamo gli eventi osservati

Nel gruppo T abbiamo:

[math]\displaystyle O_T = 10[/math]

eventi osservati.

Gli eventi attesi sono la somma dell’ultima colonna della tabella:

[math]\displaystyle E_T \approx 11,167[/math]

Pertanto:

[math]\displaystyle 10 – 11,167 \approx -1,167[/math]

Il segno negativo indica che nel gruppo T si sono verificati meno eventi di quelli attesi sotto l’ipotesi nulla.

Ma, ancora una volta, non possiamo interpretare questa differenza senza considerare la sua variabilità.


Passo 6 — Calcoliamo la varianza

Per ogni tempo utilizziamo:

[math]\displaystyle V_i = \frac{n_{Ti} n_{Ci} d_i (n_i – d_i)}{n_i^2 (n_i – 1)}[/math]

In questo esercizio abbiamo sempre:

[math]\displaystyle d_i = 1[/math]

perché non ci sono eventi simultanei.

La varianza complessiva è:

[math]\displaystyle V = \sum_i V_i[/math]

e dalla tabella dei risk set otteniamo:

[math]\displaystyle V \approx 4,688[/math]


Passo 7 — Calcoliamo la statistica del Logrank

La statistica è:

[math]\displaystyle \chi^2 = \frac{(O_T – E_T)^2}{V}[/math]

Sostituendo:

[math]\displaystyle \chi^2 = \frac{(10 – 11,167)^2}{4,688}[/math]

da cui:

[math]\displaystyle \boxed{\chi^2 \approx 0,290}[/math]

Per due gruppi abbiamo:

[math]\displaystyle df = 1[/math]

e il valore critico al livello:

[math]\displaystyle \alpha = 0,05[/math]

è:

[math]\displaystyle 3,841[/math]

Poiché:

[math]\displaystyle 0,290 < 3,841[/math]

non rifiutiamo l’ipotesi nulla.


Conclusione

Non emerge una differenza statisticamente significativa tra le due curve di sopravvivenza.

Questo risultato può sembrare sorprendente perché i tempi degli eventi non sono distribuiti nello stesso modo nei due gruppi.

Ma il Logrank non chiede semplicemente:

“Quale gruppo ha avuto prima o dopo gli eventi?”

Costruisce invece, a ogni tempo, un confronto tra:

[math]\displaystyle \boxed{\text{eventi osservati}}[/math]

e

[math]\displaystyle \boxed{\text{eventi attesi}}[/math]

tenendo conto del numero di soggetti ancora a rischio.

Perché questo esempio è importante?

Questo esercizio mostra anche perché il Logrank non può essere sostituito da un semplice confronto del numero finale di eventi.

Entrambi i gruppi hanno infatti:

[math]\displaystyle 10 \text{ eventi}[/math]

ma il test considera quando questi eventi si verificano e quanti soggetti erano ancora a rischio in ciascun momento.

Il tempo, quindi, non è un’informazione accessoria.

È parte integrante del dato.


Cosa succede se gli eventi vengono ritardati?

Supponiamo ora che gli eventi nel gruppo T si verifichino sistematicamente più tardi.

Il numero totale degli eventi potrebbe rimanere:

[math]\displaystyle 10[/math]

ma il trattamento avrebbe una curva di sopravvivenza migliore per una parte significativa del follow-up.

Il Logrank può quindi rilevare una differenza che una semplice tabella finale non vedrebbe.

Questo è il motivo per cui il tempo è informazione.


Esercizio 5 — Potenza statistica: contano gli eventi

Consideriamo un trial:

  • 200 pazienti nel gruppo A;
  • 200 nel gruppo B;
  • HR atteso = 0.75;
  • [math]\alpha = 0.05[/math];
  • potenza desiderata = 80%.

Sono stati osservati:

  • 85 eventi in A;
  • 100 eventi in B.

Totale:

[math]\displaystyle D = 185[/math]

Passo 1 — Perché il numero di eventi è importante?

Nel Logrank l’informazione statistica disponibile dipende fortemente dal numero di eventi osservati.

Avere 400 pazienti non significa necessariamente avere 400 unità di informazione.

Se molti pazienti sono censurati perché:

  • lo studio termina troppo presto;
  • il follow-up è breve;
  • il fenomeno è raro;

il numero effettivo di eventi può essere basso.

Passo 2 — Numero di eventi necessario

Una forma comune dell’approssimazione di Freedman, per allocazione 1:1 e test bilaterale, è:

[math]\displaystyle D \approx \frac{4(z_{\alpha/2} + z_\beta)^2}{[\log(HR)]^2}[/math]

Con:

[math]\displaystyle HR = 0.75[/math]

[math]\displaystyle z_{\alpha/2} = 1.96[/math]

e:

[math]\displaystyle z_\beta \approx 0.842[/math]

otteniamo circa:

[math]\displaystyle D \approx 379[/math]

eventi.

Il nostro studio ne ha soltanto:

[math]\displaystyle 185[/math]

Passo 3 — Stima approssimata della potenza

Con 185 eventi, l’informazione disponibile è circa la metà di quella necessaria.

L’approssimazione porta a una potenza intorno al:

[math]\displaystyle 50\%[/math]

anziché all’80%.

Conclusione

Lo studio è fortemente sotto-dimensionato rispetto all’effetto che si voleva rilevare.

Ma attenzione:

un risultato non significativo in uno studio underpowered non dimostra che il trattamento sia inefficace.

Dimostra che i dati raccolti potrebbero non essere sufficienti per distinguere l’effetto dal rumore statistico.


Commento applicativo

Questo concetto vale anche fuori dalla ricerca clinica.

Immaginiamo di studiare il churn di un SaaS.

Abbiamo 100.000 clienti, ma soltanto 300 churn durante il periodo osservato.

Il numero totale di clienti può sembrare enorme.

Tuttavia, per alcune analisi di survival, l’informazione disponibile è determinata soprattutto dal numero e dalla distribuzione temporale degli eventi.

La domanda corretta non è soltanto:

“Quanti clienti abbiamo?”

ma:

“Quanti eventi abbiamo osservato e con quale distribuzione temporale?”


Esercizio 6 — Quando il Logrank standard non basta

Consideriamo un trial in cui un nuovo trattamento produce un effetto molto particolare.

Durante i primi 12 mesi:

  • il beneficio è modesto.

Dopo 12 mesi:

  • il beneficio diventa molto più evidente.

Questo può accadere, per esempio, con alcuni trattamenti il cui effetto biologico richiede tempo per manifestarsi.

In una situazione del genere le curve di Kaplan-Meier possono inizialmente essere molto vicine e successivamente separarsi.

Passo 1 — Il problema della non-proportional hazards

Supponiamo che l’effetto relativo sia diverso nei due periodi.

Non possiamo descriverlo bene con un unico:

[math]\displaystyle HR[/math]

costante nel tempo.

Questo è un caso di non-proportional hazards.

Passo 2 — Il Logrank standard

Il Logrank standard continua comunque a produrre una statistica globale.

Ma quella statistica riassume l’intero follow-up.

Se l’effetto:

  • è piccolo all’inizio;
  • molto grande dopo;

il test globale può non rappresentare adeguatamente la struttura temporale dell’effetto.


Test di Fleming-Harrington

Una possibile alternativa è utilizzare test di Logrank pesati.

La famiglia di Fleming-Harrington utilizza pesi della forma:

[math]\displaystyle w(t) = \hat S(t)^\rho [1 – \hat S(t)]^\gamma[/math]

La scelta di [math]\rho[/math] e [math]\gamma[/math] determina quali parti del follow-up ricevono maggiore peso.

Per esempio:

  • alcuni pesi privilegiano gli eventi iniziali;
  • altri gli eventi tardivi.

Questo può essere particolarmente utile quando abbiamo un’ipotesi scientifica plausibile su quando dovrebbe manifestarsi l’effetto.

Attenzione

La scelta dei pesi non dovrebbe essere fatta semplicemente dopo aver guardato i dati e scelto quello che produce il p-value migliore.

Quando possibile, la strategia dovrebbe essere:

definita a priori nel protocollo di analisi.


Un’altra alternativa: RMST

Quando le proportional hazards non sono plausibili, una misura molto interessante è la Restricted Mean Survival Time, o RMST.

La RMST fino al tempo [math]\tau[/math] è:

[math]\displaystyle RMST(\tau) = \int_0^\tau S(t) \, dt[/math]

Intuitivamente rappresenta:

il tempo medio di sopravvivenza atteso entro un orizzonte temporale prefissato.

Possiamo quindi confrontare:

[math]\displaystyle RMST_A(\tau) – RMST_B(\tau)[/math]

Questo risultato è spesso più facilmente interpretabile di un unico hazard ratio quando le curve non sono proporzionali.

Esempio

Se:

[math]\displaystyle RMST_A(24) = 18.4[/math]

e:

[math]\displaystyle RMST_B(24) = 15.9[/math]

possiamo dire:

entro i primi 24 mesi, il gruppo A presenta una sopravvivenza media ristretta superiore di 2,5 mesi.

Per un decisore questo può essere molto più intuitivo di:

[math]\displaystyle HR = 0.72[/math]


Python: Kaplan-Meier e Logrank

Il calcolo manuale è importante per capire il metodo.

In un’analisi reale, però, utilizziamo librerie statistiche.

Una soluzione molto utilizzata in Python è lifelines.

import pandas as pd

from lifelines import KaplanMeierFitter
from lifelines.statistics import logrank_test

Supponiamo di avere:

df = pd.DataFrame({
    "time": [5, 10, 12, 15, 18, 20,
             3, 7, 11, 14, 16, 17],
    "event": [1, 1, 1, 1, 1, 1,
              1, 1, 1, 1, 1, 1],
    "group": ["T"] * 6 + ["C"] * 6
})

Separiamo i due gruppi:

T = df[df["group"] == "T"]
C = df[df["group"] == "C"]

Kaplan-Meier

kmf_T = KaplanMeierFitter()
kmf_C = KaplanMeierFitter()

kmf_T.fit(
    T["time"],
    event_observed=T["event"],
    label="Trattamento"
)

kmf_C.fit(
    C["time"],
    event_observed=C["event"],
    label="Controllo"
)

Possiamo poi visualizzare le curve:

import matplotlib.pyplot as plt

ax = kmf_T.plot()
kmf_C.plot(ax=ax)

plt.xlabel("Tempo")
plt.ylabel("Probabilità di sopravvivenza")
plt.title("Curve di Kaplan-Meier")
plt.show()

Curve di Kaplan-Meier


Eseguiamo il Logrank

Il confronto può essere effettuato con:

result = logrank_test(
    T["time"],
    C["time"],
    event_observed_A=T["event"],
    event_observed_B=C["event"]
)

print(result.summary)
   test_statistic         p  -log2(p)
0        0.844638  0.358074  1.481671

L’output contiene, tra le altre informazioni:

  • statistica del test;
  • p-value.

Interpretazione

Se:

[math]\displaystyle p < 0.05[/math]

rifiutiamo [math]H_0[/math] al livello di significatività del 5%.

Se:

[math]\displaystyle p \ge 0.05[/math]

non abbiamo evidenza sufficiente per rifiutare [math]H_0[/math].

Ancora una volta:

non rifiutare [math]H_0[/math] non significa dimostrare che le curve siano identiche.


Dal Logrank al modello di Cox

Il Logrank risponde principalmente alla domanda:

Le curve differiscono?

Ma spesso vogliamo sapere anche:

Quanto differiscono?

Qui entra in gioco il modello di Cox.

Il modello può essere scritto come:

[math]\displaystyle h(t|X) = h_0(t) \exp(\beta X)[/math]

e consente di stimare l’hazard ratio:

[math]\displaystyle HR = e^\beta[/math]

In Python:

from lifelines import CoxPHFitter

# CoxPHFitter richiede che tutte le covariate siano numeriche.
# Dobbiamo quindi trasformare la colonna 'group' da stringa a valore numerico.
# Metodo 1: dummy encoding (più generale, utile se hai più gruppi)
df_cox = pd.get_dummies(df, columns=["group"], drop_first=True)

# Metodo 2: mapping diretto (più compatto per due soli gruppi)
# df_cox = df.copy()
# df_cox["group"] = df_cox["group"].map({"T": 1, "C": 0})

cph = CoxPHFitter()

cph.fit(
    df_cox,
    duration_col="time",
    event_col="event"
)

cph.print_summary()

L’output conterrà, tra le altre informazioni:

  • il coefficiente [math]\beta[/math] associato al gruppo;
  • l’hazard ratio [math]HR = e^\beta[/math];
  • l’intervallo di confidenza al 95%;
  • il p-value per il test di Wald.

Se il gruppo T è codificato come 1 e il gruppo C come 0 (o se usi il dummy group_T), un HR < 1 indica che il trattamento T è associato a un rischio ridotto rispetto al controllo.

Nota tecnica 

Se usi pd.get_dummies(drop_first=True), la colonna group_C verrà omessa e il modello stimerà l’effetto di group_T rispetto alla categoria di riferimento (C). Questo è equivalente al confronto del Logrank, ma con l’aggiunta della stima puntuale dell’HR e della sua incertezza.

Forse potrebbe interessarti anche:  Distribuzione di Poisson: 6 esercizi svolti con soluzioni e spiegazioni

Se invece usi il mapping {"T": 1, "C": 0}, il coefficiente rappresenta direttamente la differenza tra T e C. Per due gruppi i due metodi producono lo stesso HR; il dummy encoding è preferibile quando hai tre o più gruppi da confrontare simultaneamente.

Output:

Come leggere l’output del modello di Cox

Supponiamo di aver eseguito il codice precedente sul dataset di esempio.

L’output di lifelines si presenta così:

model                          lifelines.CoxPHFitter
duration col                   'time'
event col                      'event'
baseline estimation            breslow
number of observations         12
number of events observed      12

Cosa ci dice questa intestazione

Il modello è stato addestrato su 12 osservazioni e ha osservato 12 eventi. Non ci sono censure nel dataset di esempio, quindi ogni paziente ha contribuito con un evento completo alla stima. La baseline è stimata con il metodo di Breslow.

La tabella dei coefficienti

coef exp(coef) se(coef) coef lower 95% coef upper 95% exp(coef) lower 95% exp(coef) upper 95% z p -log2(p)
group_T -0.59 0.56 0.65 -1.86 0.68 0.16 1.98 -0.91 0.36 1.46

Il coefficiente [math]\beta[/math]

coef = -0.59 è la stima di [math]\beta[/math] per la variabile group_T. Il segno negativo indica che il gruppo T è associato a un hazard inferiore rispetto al gruppo di riferimento C.

L’hazard ratio [math]HR = e^\beta[/math]

exp(coef) = 0.56 è l’HR. Significa che, sotto il modello, il rischio istantaneo nel gruppo T è circa il 56% di quello nel gruppo C. In termini clinici: una riduzione del 44% del rischio.

Ma attenzione: questo è il valore puntuale. Dobbiamo guardare l’incertezza.

Intervallo di confidenza al 95%

L’IC per l’HR va da 0.16 a 1.98. Poiché include il valore 1 (che corrisponde a nessuna differenza), non possiamo escludere che l’effetto reale sia nullo. L’HR potrebbe essere favorevole a T (0.16), favorevole a C (1.98) o vicino all’assenza di effetto.

Il p-value e il test di Wald

p = 0.36 e -log2(p) = 1.46. Al livello [math]\alpha = 0.05[/math], il coefficiente non è statisticamente significativo. Non abbiamo evidenza sufficiente per affermare che il trattamento T modifichi l’hazard rispetto a C.

Nota importante

Se confronti questo output con il Logrank eseguito in precedenza sullo stesso dataset, noterai qualcosa di interessante:

  • Logrank: test statistic ≈ 0.84, p ≈ 0.36, -log2(p) ≈ 1.48
  • Cox log-likelihood ratio test: 0.84 on 1 df, -log2(p) ≈ 1.48

I valori sono praticamente identici. Questo non è un caso: quando confrontiamo due gruppi senza altre covariate, il test del rapporto di verosimiglianza del modello di Cox è asintoticamente equivalente al test di Logrank. I due metodi rispondono alla stessa domanda con strumenti diversi, ma convergono sullo stesso risultato.

Le metriche di bontà del modello

Concordance = 0.56

L’indice di concordanza (o C-index) misura la capacità del modello di ordinare correttamente le coppie di soggetti in base al rischio. Un valore di 0.50 indica classificazione casuale; 1.00 indica classificazione perfetta.

Con 0.56, il modello discrimina appena meglio del caso. Questo era atteso: abbiamo un solo predittore binario su 12 osservazioni, e il predittore non è significativo. Non possiamo pretendere potere predittivo da questi dati.

Partial AIC = 41.13

L’AIC (Akaike Information Criterion) penalizza la verosimiglianza per il numero di parametri. Con un solo predittore, questo valore ha scarso interesse interpretativo. Diventerebbe utile se confrontassimo più modelli (per esempio, uno con e uno senza una covariata aggiuntiva): preferiremmo il modello con AIC inferiore.

Sintesi dell’interpretazione

  • Effetto puntuale: il gruppo T mostra un HR di 0.56, suggerendo una possibile riduzione del rischio.
  • Incertezza: l’intervallo di confidenza è molto ampio (0.16–1.98) e include 1.
  • Significatività: il p-value è 0.36, non significativo.
  • Conclusione: con questi dati non possiamo affermare che T sia superiore a C. La stima puntuale è promettente, ma il campione è troppo piccolo per trarre inferenze affidabili.

 

Questo esempio, pur essendo didattico, illustra un errore da evitare nella pratica: non guardare solo l’HR puntuale. Un HR di 0.56 può sembrare clinicamente rilevante, ma se l’intervallo di confidenza spazia da 0.16 a 1.98 e il p-value è 0.36, quel numero è instabile. In uno studio reale, questo risultato richiederebbe un campione molto più grande per essere confermato o confutato.

Inoltre, la concordanza di 0.56 ci ricorda che un modello di Cox con un solo predittore non significativo ha potere predittivo quasi nullo. Se il nostro obiettivo è prognosticare, dobbiamo arricchire il modello con covariate rilevanti (età, stadio, biomarcatori) e valutare il miglioramento del C-index.


E se la proportional hazards viene violata?

Il modello di Cox standard può diventare problematico se:

[math]\displaystyle HR(t)[/math]

varia significativamente nel tempo.

Possiamo allora valutare:

  • covariate tempo-dipendenti;
  • modelli piecewise;
  • test di Logrank pesati;
  • RMST;
  • modelli di sopravvivenza alternativi.

La scelta dipende dalla domanda scientifica.

Non esiste un “test migliore” in assoluto.


Logrank: errori da evitare

Errore 1 — Usare una tabella 2×2

Se abbiamo soltanto il numero finale di eventi, non stiamo eseguendo un vero Logrank.

Errore 2 — Ignorare la censura

Un censurato non equivale a un soggetto senza evento.

Errore 3 — Confondere hazard e probabilità

L’hazard è un concetto di rischio istantaneo, non semplicemente la probabilità cumulativa di evento.

Errore 4 — Dire che PH significa hazard costante

Non è così. PH significa che il rapporto tra gli hazard rimane costante nel tempo.

Errore 5 — Interpretare [math]p > 0.05[/math] come “nessun effetto”

Un risultato non significativo può derivare anche da potenza insufficiente.

Errore 6 — Guardare soltanto il numero di pazienti

Nella pianificazione della survival analysis il numero di eventi è fondamentale.

Errore 7 — Usare un unico HR quando le curve non sono proporzionali

Un HR medio può nascondere una dinamica temporale molto importante.

Errore 8 — Scegliere il test pesato dopo aver visto il risultato

La scelta dei pesi dovrebbe, quando possibile, essere definita prima dell’analisi.


Una strategia pratica per analizzare dati di sopravvivenza

Possiamo riassumere il workflow in questo modo:

Definisci evento e orizzonte temporale
              ↓
       Prepara i dati
              ↓
   Identifica le censure
              ↓
     Kaplan-Meier
              ↓
   Esamina le curve
              ↓
       Logrank
              ↓
    ┌─────────┴─────────┐
    ↓                   ↓
PH plausibile       PH dubbia/violata
    ↓                   ↓
Logrank + Cox      Test pesati / RMST /
                   Cox time-varying
              ↓
      Interpreta l'effetto
              ↓
     Valuta potenza e
     numero di eventi

Questo workflow è molto più importante della memorizzazione della formula.


Tabella decisionale

Situazione Approccio utile
Due gruppi con tempi di evento Logrank
Due gruppi con censure Logrank
Più di due gruppi Logrank multi-group
Variabile di stratificazione importante Logrank stratificato
Stima dell’effetto Modello di Cox
Proportional hazards plausibile Cox standard
Effetto variabile nel tempo Cox time-varying
Beneficio prevalentemente tardivo Fleming-Harrington o altri test pesati
Curve che si incrociano RMST e/o test pesati
Solo stato finale vivo/morto Test per proporzioni, non Logrank
Studio con pochi eventi Analisi della potenza e del numero di eventi

La lezione più importante

Il test di Logrank non è semplicemente una formula.

È un modo diverso di pensare ai dati.

In un problema classico possiamo chiederci:

Quanti clienti hanno fatto churn?

Nella survival analysis la domanda diventa:

Quando hanno fatto churn e quanti clienti erano ancora a rischio in quel momento?

In un trial clinico non chiediamo soltanto:

Quanti pazienti sono deceduti?

Chiediamo:

Quando si sono verificati i decessi e quanti pazienti erano ancora sotto osservazione e a rischio?

Questa differenza trasforma completamente l’analisi.


In sintesi

Il Logrank è uno degli strumenti fondamentali della survival analysis perché permette di confrontare curve di sopravvivenza tenendo conto:

  • del tempo;
  • degli eventi;
  • delle censure;
  • dei soggetti ancora a rischio.

Il procedimento può essere sintetizzato in cinque passaggi:

  1. Costruire i risk set.
  2. Calcolare gli eventi attesi.
  3. Confrontarli con gli eventi osservati.
  4. Calcolare la varianza e la statistica [math]\chi^2[/math].
  5. Interpretare il risultato insieme alle curve di Kaplan-Meier e al contesto applicativo.

Ma il punto più importante arriva dopo il calcolo.

Un buon analista non si limita a chiedere:

“Il p-value è inferiore a 0,05?”

Deve chiedersi anche:

  • Le curve sono proporzionali?
  • Quanto è grande l’effetto?
  • Quando compare l’effetto?
  • Quanti eventi abbiamo osservato?
  • Il follow-up è sufficiente?
  • Le censure possono influenzare l’analisi?
  • Il risultato è clinicamente o economicamente rilevante?
  • Un unico hazard ratio descrive davvero il fenomeno?

La survival analysis è potente proprio perché obbliga a considerare il tempo come informazione.

E questo è il vero significato del test di Logrank:

non confrontare soltanto quanti eventi si verificano, ma confrontare come il rischio di evento evolve nel tempo.

📚 Per approfondire: Churn, sopravvivenza e inferenza statistica

Se vuoi approfondire come statistica inferenziale, analisi della sopravvivenza e machine learning possono aiutare a comprendere e prevedere il comportamento dei clienti, ecco una selezione di guide ed esercizi pratici:

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

👉 Come prevedere il churn con Python: guida completa al Machine Learning e SHAP

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

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

👉 I test di ipotesi spiegati semplicemente: come la statistica decide se i tuoi dati stanno mettendo in discussione la realtà

 

Pubblicità