Reputation: 381
In the meta-analysis package metafor in R, there is a blup() function for rma.uni() but not rma.mv(). I have an rma.mv model with a random intercept term. If I use:
predict.rma(model,transf=exp)
then I get an estimate from my fixed effect moderators for each datapoint in my original dataset, and:
ranef(model,transf=exp)
gives me predictions for each level of my random effect.
Is there then a way to combine the information from these two functions to get combined random and fixed effect BLUPs, as would be provided by the blup() function?
(I have tried taking the mean of both the fixed effect estimate and the random effect prediction for each datapoint in my original dataset, and this looks right when I plot it ... but surely it's not that simple?)
Upvotes: 1
Views: 746
Reputation: 381
In the process of following Wolfgang's very helpful instructions in the marked answer, I created some code to do this with an example dataset. Posting in case it helps anyone else:
Update: following Wolfgang's comment below, I have removed the code for the CIs and replaced it with code to calculate the SE for the BLUP.
#load packages and example data
library(metafor)
library(plyr)
library(ggplot2)
dat<-dat.konstantopoulos2011
dat
#make a model - note I have nested random effects
#(no idea if it actually makes sense with this example dataset!)
mod<-rma.mv(yi,vi,mods=~year,random=~1|district/school,data=dat)
#predict from the model (without exponentiating) and attach to original data
preds<-predict.rma(mod,addx=TRUE)
dat$pred<-preds$pred
dat$ci.ub<-preds$ci.ub
dat$ci.lb<-preds$ci.lb
dat$fe_se<-preds$se
dat$dist.sch<-interaction(dat$district,dat$school) #create a label for each district/school
#get the district random effects and label them
dist_re<-data.frame(ranef(mod)$district)
dist_re$district<-rownames(dist_re)
#get the school random effects and label them
sch_re<-data.frame(ranef(mod)$`district/school`)
sch_re$dist.sch<-rownames(sch_re)
sch_re$dist.sch<-gsub("/",".",sch_re$dist.sch)
colnames(sch_re)<-c("intrcpt2","se2","pi.lb2","pi.ub2","dist.sch") #to avoid duplicate colnames later
#join the district and school random effects to the data by labels
plotdat<-join(dat,dist_re,by="district")
plotdat2<-join(plotdat,sch_re,by="dist.sch")
#create the blups and intervals by adding the fixed effect estimates and random effect predictions,
#and exponentiating:
plotdat2$blup<-exp(plotdat2$pred+plotdat2$intrcpt+plotdat2$intrcpt2)
plotdat2$blup.se<-sqrt((plotdat2$fe_se^2)+(plotdat2$se^2)+(plotdat2$se2^2))
#forest plot of BLUPs and their SEs just to check they make sense:
ggplot(plotdat2, aes(y=dist.sch, x=blup, xmin=blup-blup.se, xmax=blup+blup.se))+
geom_point()+
geom_errorbarh(height=.2)+
ylab('District and school')+
geom_vline(xintercept=1,linetype='dashed')+
xlim(0,5)+
theme_bw()
Upvotes: 1
Reputation: 3395
You can add (don't take the mean) what predict()
gives you to what ranef()
gives you, but you have to be careful in correctly 'lining up' the BLUPs with the rows from predict()
. The row names from ranef()
tell you the levels for which the BLUPs are computed, so you can use them to match things up correctly. Also, first add them, then you can exponentiate the values, not the other way around.
Upvotes: 1