Analysis of time-stratified casecrossover studies in environmental
epidemiology using Stata
Aurelio Tobías
Spanish Council for Scientific Research (CSIC), Barcelona, Spain
Ben Armstrong and Antonio Gasparrini
London School of Hygiene and Tropical Medicine, UK
2014 UK Stata Users Group meeting
London, 12th September 2014
Background
• The time stratified case crossover design is a
popular alternative to conventional time
series regression for analysing associations
between time series of environmental
exposures (air pollution, weather) and counts
of health outcomes
The case-crossover design
• Proposed by Maclure (1991) to study transient
effects on the risk of acute health events
… compared to your usual
routine?
Have you
made ​any
unusual activity
…
Health
event
The case-crossover design
• Proposed by Maclure (1991) to study transient
effects on the risk of acute health events
Exposed?
Control period
Exposed?
Risk period
Health
event
The case-crossover design
• Proposed by Maclure (1991) to study transient
effects on the risk of acute health events
Exposed?
Control period
• Analysis likewise a
matched case-control
Exposed?
Risk period
Health
event
Control
Exp. No
Risk Exp.
period No
a
c
b
d
OR = b/c
Application to environmental studies
• Firstly adapted to air pollution studies
– Philadelphia (Neas et al. 1999) and Barcelona (Sunyer et al.
2000)
• comparing exposure levels for a given day (t) when
health event occurs vs. levels before (t-7) and after
(t+7) the health event
• Allows to control for time-trend and seasonality by
design, since compares exposure levels between
same weekdays within each month of each year
Time-stratified case-crossover
(Figueiras et al. 2010)
Option 1: conditional logistic regression
• Dataset needs to be reshaped from time-series
format to individual matched case-control by using
the new command,
• . mkcco vary, date(vardate)
–
–
–
–
This also creates three new variables,
case case days (=1)
wn
weight observations by n events on case day
ccset set num. to match case-control days
• Then, use Stata’s clogit command
. use madrid, clear
. list date y pm10 temp in 1/31, noobs clean
date
01jan2003
02jan2003
03jan2003
04jan2003
05jan2003
06jan2003
07jan2003
08jan2003
09jan2003
10jan2003
11jan2003
12jan2003
13jan2003
14jan2003
15jan2003
16jan2003
17jan2003
18jan2003
19jan2003
20jan2003
21jan2003
22jan2003
23jan2003
24jan2003
25jan2003
26jan2003
27jan2003
28jan2003
29jan2003
30jan2003
31jan2003
y
64
56
73
69
71
68
63
85
67
80
65
95
60
76
77
75
76
75
74
79
73
72
72
74
59
77
64
65
74
77
55
pm10
14
12
16
14
17
9
19
13
13
22
23
17
45
60
72
54
65
43
12
19
16
21
25
46
42
26
22
41
18
17
17
temp
9.6
11
9.8
8.8
4.3
7
3
6.8
4.6
2.7
1
.85
.5
.45
1.3
2.6
2
.8
6.3
5.8
8
6.7
7
6.2
8.1
10
15
9.7
5.7
4.8
2.3
Sun
Mon
Tue
Wed
Thu
Fri
Sat
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
. generate dow = dow(date)
. list date y pm10 temp in 1/31 if dow==1, noobs clean
date
06jan2003
13jan2003
20jan2003
27jan2003
y
68
60
79
64
pm10
9
45
19
22
temp
7
.5
5.8
15
. mkcco y, date(date)
Dataset reshaped from 1096 to 5480 obs. (1096 case days and 4384 control days).
New variables case, wn and ccset have been added to the resaphed dataset.
Sun
Mon
Tue
Wed
Thu
Fri
Sat
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
. list date y pm10 temp case ccset wn in 1/36 if dow==1, noobs clean
date
06jan2003
13jan2003
20jan2003
27jan2003
...
y
68
60
79
64
pm10
9
45
19
22
temp
7
.5
5.8
14.8
case
1
0
0
0
ccset
2003021
2003021
2003021
2003021
wn
68
68
68
68
Sun
Mon
Tue
Wed
Thu
Fri
Sat
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
...
date
06jan2003
13jan2003
20jan2003
27jan2003
y
68
60
79
64
pm10
9
45
19
22
temp
7
.5
5.8
14.8
case
0
1
0
0
ccset
2003022
2003022
2003022
2003022
wn
60
60
60
60
Sun
Mon
Tue
Wed
Thu
Fri
Sat
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
...
date
06jan2003
13jan2003
20jan2003
27jan2003
y
68
60
79
64
pm10
9
45
19
22
temp
7
.5
5.8
14.8
case
0
0
1
0
ccset
2003023
2003023
2003023
2003023
wn
79
79
79
79
Sun
Mon
Tue
Wed
Thu
Fri
Sat
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
...
date
06jan2003
13jan2003
20jan2003
27jan2003
y
68
60
79
64
pm10
9
45
19
22
temp
7
.5
5.8
14.8
case
0
0
0
1
ccset
2003024
2003024
2003024
2003024
wn
64
64
64
64
. clogit case pm10 [w=wn], group(ccset)
(frequency weights assumed)
...
Conditional (fixed-effects) logistic regression
Log likelihood =
-98913.41
Number of obs
LR chi2(1)
Prob > chi2
Pseudo R2
=
=
=
=
295025
8.39
0.0038
0.0000
-----------------------------------------------------------------------------case |
Coef.
Std. Err.
z
P>|z|
[95% Conf. Interval]
-------------+---------------------------------------------------------------pm10 |
.0007406
.0002552
2.90
0.004
.0002404
.0012408
------------------------------------------------------------------------------
Option 1: conditional logistic regression
• Advantage
– Similar approach to a matched
case-control study, being
familiar to the epidemiologist
• Limitations
– Unfriendly data management
– Large (huge) data-sets at
individual level
– Slow convergence when fitting
interaction terms for
individual factors (sex, age)
– Cannot account for
overdispersion and residual
autocorrelation
Option 2: Poisson regression
• Lu and Zeger (2007)
– “ … the time-stratified case-crossover design leads to the
same estimate as obtained from a Poisson regression with
dummy variables indicating the strata”
• Strata defined by the 3-way interaction between
year, month and day of week
• Either poisson or glm (jointly with the scale
option) Stata’s commands can be used
.
.
.
.
use madrid, clear
generate yy = year(date)
generate mm = month(date)
generate dow = dow(date)
. poisson y pm10 i.yy##i.mm#i.dow
...
Poisson regression
Log likelihood =
-3787.589
Number of obs
LR chi2(252)
Prob > chi2
Pseudo R2
=
=
=
=
1096
1374.12
0.0000
0.1535
-----------------------------------------------------------------------------y |
Coef.
Std. Err.
z
P>|z|
[95% Conf. Interval]
-------------+---------------------------------------------------------------pm10 |
.0007406
.0002552
2.90
0.004
.0002404
.0012408
|
...
252 parameters!
|
_cons |
4.35927
.0563535
77.36
0.000
4.248819
4.469721
------------------------------------------------------------------------------
. glm y pm10 i.yy##i.mm#i.dow, family(poisson) link(log) scale(x2)
...
Generalized linear models
Optimization
: ML
Deviance
Pearson
=
=
1069.73306
1065.616046
Variance function: V(u) = u
Link function
: g(u) = ln(u)
No. of obs
Residual df
Scale parameter
(1/df) Deviance
(1/df) Pearson
=
=
=
=
=
1096
843
1
1.26896
1.264076
[Poisson]
[Log]
AIC
= 7.373338
Log likelihood
= -3787.588997
BIC
= -4830.78
-----------------------------------------------------------------------------|
OIM
y |
Coef.
Std. Err.
z
P>|z|
[95% Conf. Interval]
-------------+---------------------------------------------------------------pm10 |
.0007406
.0002869
2.58
0.010
.0001782
.001303
|
...
|
_cons |
4.35927
.0633589
68.80
0.000
4.235088
4.483451
-----------------------------------------------------------------------------(Standard errors scaled using square root of Pearson X2-based dispersion.)
Option 2: Poisson regression
• Advantages
– Avoids reshape of dataset
keeping original time-series
format
– Can account for
overdispersion and residual
autocorrelation
• Limitations
– Large number of interaction
parameters, slowing the
convergence time (even
making difficult it with missing
data)
– Even slower when fitting
interaction terms for
individual factors (sex, age)
Option 3: Conditional Poisson regression
• Armstrong and Gasparrini (ISEE 2011)
– “ … Poisson models with large numbers of indicator variables
can alternatively be fit with conditional Poisson models,
conditioning on numbers of events in the time stratum”
– Firstly proposed by Farrington (1995) for the self-controlled
case-series design for vaccine safety studies
• Strata defined by grouping same weekday within each
month of each year, and then use Stata’s xtpoisson
command jointly with the fe option
• But overdispersion needs to accounted for with the new
xtpois_ovdp command
. egen set = group(yy mm dow)
. xtset set date
...
. xtpoisson y pm10, fe
...
Conditional fixed-effects Poisson regression
Group variable: set
Log likelihood
= -2854.4979
Number of obs
Number of groups
=
=
1096
252
Obs per group: min =
avg =
max =
4
4.3
5
Wald chi2(1)
Prob > chi2
=
=
8.42
0.0037
-----------------------------------------------------------------------------y |
Coef.
Std. Err.
z
P>|z|
[95% Conf. Interval]
-------------+---------------------------------------------------------------pm10 |
.0007406
.0002552
2.90
0.004
.0002404
.0012408
-----------------------------------------------------------------------------. xtpois_ovdp
Estimate and standard errors corrected for over-dipersion
df: 843 ; pearson x2: 1065.6 ; dispersion:
1.26
-----------------------------------------------------------------------------y |
Coef.
Std. Err.
z
P>|z|
[95% Conf. Interval]
-------------+---------------------------------------------------------------pm10 |
.0007406
.0002869
2.58
0.010
.0001782
.001303
------------------------------------------------------------------------------
CPU time
• My example (3 years data, 60 events/day)
– clogit
– poisson
– xtpoisson
0.181 sec.
2.111 sec.
0.066 sec.
Option 3: Conditional Poisson regression
• Advantages
– Avoids reshape of dataset
keeping original time-series
format
– Can account for
overdispersion and residual
autocorrelation
– Easy fit of interaction terms
for individual factors (sex, age)
with faster convergence
• Limitations
–?
Summary
• Case-crossover studies can easily be analysed using
Stata
1) Conditional logistic regression requires unfriendly data
management, and large (huge) data-sets at individual
level
2) Poisson, 3-way interaction, regression requires to fit large
number of interaction parameters, making it difficult
convergence
3) Conditional Poisson seems to solve both
Thanks
for your
attention!
Thanks
for your
attention!