Meta regression
Metafor
• Package: Metafor (by Wolfgang Viechtbauer)
• The metafor package consists of a collection of functions for conducting meta-analyses in R. Fixed- and random-effects models (with and without moderators) can be fitted via the general linear (mixed-effects) model.
• Function: rma
Pooled effect
Effect in each city
Steps
• Step 1. Calculate beta and se for each city using GLM
• Step 2. Derive % change of risk for cities
• Step 3. call ‘rma’ to estmate the pooled effect.
• Step 4. Plot
R code for step 1
Estimate each city’s beta, se
R code for step 2
Save beta and se in dat.meta matrix
% change of risk for cities
Before Step 3
•Create two moderators
Step 3(1) Call ‘rma’ functionlibrary(metafor)
### random-effects model
rma_out=rma(beta, var, data=dat.meta, method="REML")
Pooled beta and s.e.
Step 3(2) Adjust for moderators
### mixed-effects model with two moderators (latitude and longitude)
rma_out2=rma(beta,var, mods=cbind(latitude,longitude), data=dat.meta, method="REML")
### using a model formula to specify the same model
rma_out3=rma(beta,var, mods=~latitude+longitude, data=dat.meta, method="REML")
Two ways are Identical
Adjusting two moderators
Still insignificant, and more negative
Step 4 Plot
(1)Derive % change of risk for pooled effect.
(2) Complete pctchangematrix with pooled and city’s % change.
(3) Plot
(Metafor 그림)
R code for plotn=dim(pctchange)[1]
rng=ceiling(range(pctchange[,2:3]))
pctor=pctchange[,1]; pctlc=pctchange[,2]; pctuc=pctchange[,3]
ylabs=c("Pooled",ccodename[1:6])
plot(pctor[n:1],seq_len(n), xlim=c(rng[1]-1,rng[2]+1),ylim=c(1,n), pch=20, cex.lab=1.2, main="Tot mortality (1992-2007)",xlab="% change of mortality",ylab="",axes=F)
segments(pctlc[n:1],seq(n), pctuc[n:1], seq(n), lmitre=9)
abline(v=0, lty=2)
axis(1,at=seq(rng[1]-1,rng[2]+1,1),labels=seq(rng[1]-1,rng[2]+1,1))
axis(2,at=seq(n,1),las=1, labels=ylabs)
text(rep(rng[2]+0.3,n),seq(1,n),adj=0,cex=1.0,paste(round(pctor[n:1],3),"%",sep=""))
box()
Y-axis values
95% CI
Define Y-axis ceiling
x-axis tick
Y-axis tick
Threshold effect
Introduction
• Relationship between temperature and mortality is known as U or V-shape
• Fitting the model with two slopes
• Lowest AIC
Temperature and Mortality
Threshold temperature
Threshold temperature (Seoul, 1992-2007)
Threshold model
• Let Θ be threshold temperature• Linear Poisson regression model
Log E(Y)=β0+ β1*temperature+ β2*(temperature-Θ)++S1(x1)+..+Sp(xp)Where (temperature- Θ)+=max{temperature- Θ, 0}
• If temperature < Θ, Log E(Y)=β0+ β1*temperature+S1(x1)+..+Sp(xp)
• If temperature > Θ, Log E(Y)=β0- β2* Θ + (β1+ β2)*temperature+S1(x1)+..+Sp(xp)
Threshold model
• Goal: Estimate the location of the threshold temperature by implementing a grid search and by identifying the temperature that minimizes the profile likelihood
Temperature
25.1 °C 25.5 °C
Steps
• Step 1. examine the association with plot
• Step 2. define the potential range of threshold
• Step 3. Fit the model
• Step 4. Calculate slopes, p-value and AIC
• Step 5. Find the best fit with the lowest AIC
Step 1. Examine relationship between Temperature and mortality
R Code for step 1data1.2=data1
s1=which(data1$meantemp<10)
data1.2[s1,"meantemp"]=NA
### relationship btw temperature and nonacc above 10C
m1=gam(nonacc~s(Lag(meantemp,1))+s(sn,k=4*8)+factor(dow)+meanhumi+meanpress,data=data1,family=quasipoisson, na.rm=T)
plot(m1, select=1, xlab=paste("Mean temperature at lag ",kk), ylab="Log RR", main=ylab2[kv])
### relationship btw temperature and nonacc above 10C
m2=gam(nonacc~s(Lag(meantemp,1))+s(sn,k=4*8)+factor(dow)+meanhumi+meanpress,data=data1.2,family=quasipoisson, na.rm=T)
plot(m2, select=1, xlab=paste("Mean temperature at lag ",kk), ylab="Log RR",
main=paste(ylab2[kv],"(>10C)"))
Tip: Treat days with meantemp below 10 °C as missing. But keep other variables as they are.1184 days had temperature below 10 °C (1 day also has missing PM10)
Results of GAM (data1 vs data1.2)
7 df for temp and 30/8 df per yr for time trend
1 missing pm10
4 df for temp and 27/8 df per yr for time trend
1 missing pm10+1183 additional missing meantemp
data1
Data1.2
Step 2. Define range of threshold
• Define potential threshold temperature
range_pt=matrix(c(20, 20, 22, 30, 30, 30 ),3,2)
• Define interval to search for threshold (by 0.1)
diff_pt=range_pt[kv,2]-range_pt[kv,1]
ndiff=((diff_pt)*10+1)
• Fill the output matrix with each slope’s beta, p-value and AIC for model fitting.
Disease lower Upper
Total 20 30
CVD 20 30
Respir 22 30
Beta1 P1 Beta2 P2 AIC threshold
20.1
20.2
20.3
Step 3. Fit the model
• In GLM, fit the modelfor (i in 1:n_for) # temperature interval by 0.1
{
data1.2$ll<-ifelse(data1.2$meantemp-M1[i,6]>0,
data1.2$meantemp-M1[i,6],0)
m11<-glm(nonacc~
+ll
+Lag(meantemp,1)
+ns(sn,df=4*8)+factor(dow)
+meanhumi+meanpress
,data=data1.2)
Log E(Y)=β0+ β1*temperature+ β2*(temperature- Θ)+ +S1(x1) +.. +Sp(xp)
β1
β2
Confounders
(temperature- Θ)+=max{temperature- Θ, 0}
Step 4. Calculate slopes, p-value, and AIC
• If temperature < Θ, Log E(Y)=β0+ β1*temperature+S1(x1)+..+Sp(xp)
• If temperature > Θ, Log E(Y)=β0- β2* Θ + (β1+ β2)*temperature+S1(x1)+..+Sp(xp)
β1
β1+ β2
(1) Left slope (β1) and p-value
(2) Calculate right slope and their p-value
ncoef=length(m11$coefficients)
c<-c(0,1,1,rep(0,1,ncoef-3))
want=c%*%m11$coefficients
se<-sqrt(t(c)%*%vcov(m11)%*%c)
Z <- want/se
p<-(1-pnorm(abs(Z)))*2
m11$coefficients
ncoef=43C=0,1,1,0,0,0,0,….,0 (=> keep ll and meantemp)want (=β1+ β2)=35.89+0.32=36.22
P-value for the riight slope (β1+ β2)
β2
β1
Step 5. Find the best fit with the lowest AIC
(1) Fill the matrix (M1)
a<-summary(m11)
M1[i,1:5]<c(a$coefficients[3,1],a$coefficients[3,4],want,p,m11$aic)
(2) Plot
abline(v=M1[order(M1[,5],decreasing=F)[1],6])
plot(AIC~threshold,data=M1)
axis(1,seq(20,30,0.1),labels=c(rep("",101)))
Beta1 P1 Beta2 P2 AIC threshold
20.1
20.2
20.3
Plot of the association of temperature and mortality (left) and AIC by threshold point (right)
22.9°C