Ho 17 anni (1995-2011) di dati relativi al certificato di morte relativi a decessi suicidi per uno stato negli Stati Uniti. C'è molta mitologia là fuori sui suicidi e sui mesi / stagioni, molti dei quali contraddittori, e della letteratura I ' ho rivisto, non ho un chiaro senso dei metodi utilizzati o la fiducia nei risultati.
Quindi ho deciso di vedere se riesco a determinare se i suicidi hanno più o meno probabilità di verificarsi in un dato mese all'interno del mio set di dati. Tutte le mie analisi sono fatte in R.
Il numero totale di suicidi nei dati è di 13.909.
Se guardi l'anno con il minor numero di suicidi, si verificano in 309/365 giorni (85%). Se guardi l'anno con il maggior numero di suicidi, si verificano in 339/365 giorni (93%).
Quindi ci sono un buon numero di giorni ogni anno senza suicidi. Tuttavia, se aggregati in tutti i 17 anni, ci sono suicidi in ogni giorno dell'anno, incluso il 29 febbraio (sebbene solo 5 quando la media è 38).
Il semplice sommare il numero di suicidi in ogni giorno dell'anno non indica una chiara stagionalità (ai miei occhi).
Aggregati a livello mensile, i suicidi medi al mese vanno da:
(m = 65, sd = 7.4, a m = 72, sd = 11.1)
Il mio primo approccio è stato quello di aggregare il set di dati per mese per tutti gli anni e fare un test chi-quadro dopo aver calcolato le probabilità attese per l'ipotesi nulla, che non vi fosse alcuna varianza sistematica nella conta dei suicidi per mese. Ho calcolato le probabilità per ogni mese tenendo conto del numero di giorni (e adeguando febbraio per gli anni bisestili).
I risultati del chi-quadrato non hanno indicato variazioni significative di mese:
# So does the sample match expected values?
chisq.test(monthDat$suicideCounts, p=monthlyProb)
# Yes, X-squared = 12.7048, df = 11, p-value = 0.3131
L'immagine seguente indica i conteggi totali al mese. Le linee rosse orizzontali sono posizionate ai valori previsti rispettivamente per febbraio, 30 giorni e 31 giorni. Coerentemente con il test chi-quadro, nessun mese è al di fuori dell'intervallo di confidenza del 95% per i conteggi previsti.
Pensavo di aver finito fino a quando non ho iniziato a indagare sui dati delle serie storiche. Come immagino molte persone, ho iniziato con il metodo di decomposizione stagionale non parametrico usando la stl
funzione nel pacchetto stats.
Per creare i dati delle serie temporali, ho iniziato con i dati mensili aggregati:
suicideByMonthTs <- ts(suicideByMonth$monthlySuicideCount, start=c(1995, 1), end=c(2011, 12), frequency=12)
# Plot the monthly suicide count, note the trend, but seasonality?
plot(suicideByMonthTs, xlab="Year",
ylab="Annual monthly suicides")
Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
1995 62 47 55 74 71 70 67 69 61 76 68 68
1996 64 69 68 53 72 73 62 63 64 72 55 61
1997 71 61 64 63 60 64 67 50 48 49 59 72
1998 67 54 72 69 78 45 59 53 48 65 64 44
1999 69 64 65 58 73 83 70 73 58 75 71 58
2000 60 54 67 59 54 69 62 60 58 61 68 56
2001 67 60 54 57 51 61 67 63 55 70 54 55
2002 65 68 65 72 79 72 64 70 59 66 63 66
2003 69 50 59 67 73 77 64 66 71 68 59 69
2004 68 61 66 62 69 84 73 62 71 64 59 70
2005 67 53 76 65 77 68 65 60 68 71 60 79
2006 65 54 65 68 69 68 81 64 69 71 67 67
2007 77 63 61 78 73 69 92 68 72 61 65 77
2008 67 73 81 73 66 63 96 71 75 74 81 63
2009 80 68 76 65 82 69 74 88 80 86 78 76
2010 80 77 82 80 77 70 81 89 91 82 71 73
2011 93 64 87 75 101 89 87 78 106 84 64 71
E poi ha eseguito la stl()
decomposizione
# Seasonal decomposition
suicideByMonthFit <- stl(suicideByMonthTs, s.window="periodic")
plot(suicideByMonthFit)
A questo punto mi sono preoccupato perché mi sembra che ci sia una componente stagionale e una tendenza. Dopo molte ricerche su Internet, ho deciso di seguire le istruzioni di Rob Hyndman e George Athanasopoulos come indicato nel loro testo online "Previsioni: principi e pratica", in particolare per applicare un modello ARIMA stagionale.
Ho usato adf.test()
e kpss.test()
per valutare la stazionarietà e ho ottenuto risultati contrastanti. Entrambi hanno respinto l'ipotesi nulla (notando che testano l'ipotesi opposta).
adfResults <- adf.test(suicideByMonthTs, alternative = "stationary") # The p < .05 value
adfResults
Augmented Dickey-Fuller Test
data: suicideByMonthTs
Dickey-Fuller = -4.5033, Lag order = 5, p-value = 0.01
alternative hypothesis: stationary
kpssResults <- kpss.test(suicideByMonthTs)
kpssResults
KPSS Test for Level Stationarity
data: suicideByMonthTs
KPSS Level = 2.9954, Truncation lag parameter = 3, p-value = 0.01
Ho quindi usato l'algoritmo nel libro per vedere se potevo determinare la quantità di differenziazione che doveva essere fatta sia per la tendenza che per la stagione. Ho finito con nd = 1, ns = 0.
Ho quindi corso auto.arima
, che ha scelto un modello che aveva sia una tendenza che una componente stagionale insieme a una costante di tipo "deriva".
# Extract the best model, it takes time as I've turned off the shortcuts (results differ with it on)
bestFit <- auto.arima(suicideByMonthTs, stepwise=FALSE, approximation=FALSE)
plot(theForecast <- forecast(bestFit, h=12))
theForecast
> summary(bestFit)
Series: suicideByMonthFromMonthTs
ARIMA(0,1,1)(1,0,1)[12] with drift
Coefficients:
ma1 sar1 sma1 drift
-0.9299 0.8930 -0.7728 0.0921
s.e. 0.0278 0.1123 0.1621 0.0700
sigma^2 estimated as 64.95: log likelihood=-709.55
AIC=1429.1 AICc=1429.4 BIC=1445.67
Training set error measures:
ME RMSE MAE MPE MAPE MASE ACF1
Training set 0.2753657 8.01942 6.32144 -1.045278 9.512259 0.707026 0.03813434
Infine, ho esaminato i residui dall'adattamento e se lo capisco correttamente, poiché tutti i valori rientrano nei limiti di soglia, si comportano come rumore bianco e quindi il modello è abbastanza ragionevole. Ho eseguito un test portmanteau come descritto nel testo, che aveva un valore ap ben superiore a 0,05, ma non sono sicuro di avere i parametri corretti.
Acf(residuals(bestFit))
Box.test(residuals(bestFit), lag=12, fitdf=4, type="Ljung")
Box-Ljung test
data: residuals(bestFit)
X-squared = 7.5201, df = 8, p-value = 0.4817
Dopo essere tornato a leggere di nuovo il capitolo sulla modellazione degli arima, ora mi rendo conto che auto.arima
ha scelto di modellare tendenza e stagione. E sto anche comprendendo che la previsione non è specificamente l'analisi che probabilmente dovrei fare. Voglio sapere se un mese specifico (o più generalmente un periodo dell'anno) deve essere contrassegnato come mese ad alto rischio. Sembra che gli strumenti nella letteratura sulle previsioni siano altamente pertinenti, ma forse non i migliori per la mia domanda. Qualsiasi input è molto apprezzato.
Sto pubblicando un collegamento a un file CSV che contiene i conteggi giornalieri. Il file è simile al seguente:
head(suicideByDay)
date year month day_of_month t count
1 1995-01-01 1995 01 01 1 2
2 1995-01-03 1995 01 03 2 1
3 1995-01-04 1995 01 04 3 3
4 1995-01-05 1995 01 05 4 2
5 1995-01-06 1995 01 06 5 3
6 1995-01-07 1995 01 07 6 2
Il conteggio è il numero di suicidi avvenuti quel giorno. "t" è una sequenza numerica da 1 al numero totale di giorni nella tabella (5533).
Ho preso nota dei commenti qui sotto e ho pensato a due cose legate alla modellazione del suicidio e delle stagioni. In primo luogo, per quanto riguarda la mia domanda, i mesi sono semplicemente dei proxy per segnare il cambio di stagione, non mi interessa se un determinato mese o non è diverso dagli altri (che ovviamente è una domanda interessante, ma non è quello che ho deciso di fare indagare). Quindi, penso che abbia senso equalizzare i mesi semplicemente usando i primi 28 giorni di tutti i mesi. Quando lo fai, ottieni un adattamento leggermente peggiore, che sto interpretando come ulteriori prove di una mancanza di stagionalità. Nell'output di seguito, il primo adattamento è una riproduzione da una risposta di seguito che utilizza i mesi con il loro numero reale di giorni, seguito da un set di dati suicidioByShortMonthin cui i conteggi dei suicidi sono stati calcolati dai primi 28 giorni di tutti i mesi. Sono interessato a ciò che la gente pensa se questo adattamento è una buona idea, non necessario o dannoso?
> summary(seasonFit)
Call:
glm(formula = count ~ t + days_in_month + cos(2 * pi * t/12) +
sin(2 * pi * t/12), family = "poisson", data = suicideByMonth)
Deviance Residuals:
Min 1Q Median 3Q Max
-2.4782 -0.7095 -0.0544 0.6471 3.2236
Coefficients:
Estimate Std. Error z value Pr(>|z|)
(Intercept) 2.8662459 0.3382020 8.475 < 2e-16 ***
t 0.0013711 0.0001444 9.493 < 2e-16 ***
days_in_month 0.0397990 0.0110877 3.589 0.000331 ***
cos(2 * pi * t/12) -0.0299170 0.0120295 -2.487 0.012884 *
sin(2 * pi * t/12) 0.0026999 0.0123930 0.218 0.827541
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
(Dispersion parameter for poisson family taken to be 1)
Null deviance: 302.67 on 203 degrees of freedom
Residual deviance: 190.37 on 199 degrees of freedom
AIC: 1434.9
Number of Fisher Scoring iterations: 4
> summary(shortSeasonFit)
Call:
glm(formula = shortMonthCount ~ t + cos(2 * pi * t/12) + sin(2 *
pi * t/12), family = "poisson", data = suicideByShortMonth)
Deviance Residuals:
Min 1Q Median 3Q Max
-3.2414 -0.7588 -0.0710 0.7170 3.3074
Coefficients:
Estimate Std. Error z value Pr(>|z|)
(Intercept) 4.0022084 0.0182211 219.647 <2e-16 ***
t 0.0013738 0.0001501 9.153 <2e-16 ***
cos(2 * pi * t/12) -0.0281767 0.0124693 -2.260 0.0238 *
sin(2 * pi * t/12) 0.0143912 0.0124712 1.154 0.2485
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
(Dispersion parameter for poisson family taken to be 1)
Null deviance: 295.41 on 203 degrees of freedom
Residual deviance: 205.30 on 200 degrees of freedom
AIC: 1432
Number of Fisher Scoring iterations: 4
La seconda cosa che ho approfondito è il problema dell'uso del mese come proxy per la stagione. Forse un indicatore migliore della stagione è il numero di ore di luce che un'area riceve. Questi dati provengono da uno stato settentrionale che presenta notevoli variazioni alla luce del giorno. Di seguito è riportato un grafico della luce del giorno dell'anno 2002.
Quando uso questi dati anziché il mese dell'anno, l'effetto è ancora significativo, ma l'effetto è molto, molto piccolo. La devianza residua è molto più grande dei modelli sopra. Se le ore di luce sono un modello migliore per le stagioni e la vestibilità non è altrettanto buona, si tratta di ulteriori prove di effetti stagionali molto piccoli?
> summary(daylightFit)
Call:
glm(formula = aggregatedDailyCount ~ t + daylightMinutes, family = "poisson",
data = aggregatedDailyNoLeap)
Deviance Residuals:
Min 1Q Median 3Q Max
-3.0003 -0.6684 -0.0407 0.5930 3.8269
Coefficients:
Estimate Std. Error z value Pr(>|z|)
(Intercept) 3.545e+00 4.759e-02 74.493 <2e-16 ***
t -5.230e-05 8.216e-05 -0.637 0.5244
daylightMinutes 1.418e-04 5.720e-05 2.479 0.0132 *
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
(Dispersion parameter for poisson family taken to be 1)
Null deviance: 380.22 on 364 degrees of freedom
Residual deviance: 373.01 on 362 degrees of freedom
AIC: 2375
Number of Fisher Scoring iterations: 4
Sto pubblicando le ore di luce nel caso in cui qualcuno voglia giocare con questo. Si noti che questo non è un anno bisestile, quindi se si desidera inserire il verbale per gli anni bisestili, estrapolare o recuperare i dati.
[ Modifica per aggiungere la trama dalla risposta eliminata (speriamo che non mi dispiaccia spostare la trama nella risposta eliminata qui alla domanda. Svannoy, se non vuoi che questa venga aggiunta dopo tutto, puoi ripristinarla)]