Michael Schmitz Michael Schmitz - 2 months ago 20
R Question

forest plot point size

In the documentation of the

metafor
library it says, that if the optional argument
psize
is unspecified, the point sizes are drawn proportional to the precision of the estimates. As far as I know, precision is the reciprocal of the variance.


  1. How does the metafor library calculate the point size from the confidence interval?

  2. How can I enlarge only the point size?
    cex
    also affects the text size.



example

library(metafor)
model_data <- read.table(dec = ",", text="
OR lower upper
age 0,9678479 0,9326182 1,002493
sex 1,0679667 0,4987457 2,280504
ApacheeII 0,9288701 0,8728417 0,984529",
header=T)

forest(x=model_data$OR,
ci.lb=model_data$lower,
ci.ub=model_data$upper,
annotate=TRUE,
cex=1.2,
at=seq(0,6,1),
refline=1,
digits=c(3,1),
xlim=c(-1,2),
xlab="OR",
slab=rownames(model_data))

Answer

As for 1:

The relevant line of code in forest.default() is:

vi <- ((ci.ub - ci.lb) / (2*qnorm(alpha/2, lower.tail=FALSE)))^2

So, the function assumes you are supplying the bounds of a symmetric Wald-tye confidence interval (CI) to the function and then back-calculates the variance based on that. This would be appropriate for log odds ratios and the corresponding CI bounds on the log scale, but you are apparently directly applying the ORs and CI bounds on the raw scale to the function. Then this makes less sense. Usually, CIs for odds ratios are actually first calculated on the log scale (and are then exponentiated). This also appears to the case for these data:

round(with(model_data, log(upper) - log(OR)), 2)
round(with(model_data, log(OR) - log(lower)), 2)

This shows that on the log scale, the CI bounds are symmetric (around log(OR)). So, these CI bounds are very likely Wald-type CIs on the log scale. So, it would make more sense to do this:

dat <- log(model_data)

forest(x=dat$OR, ci.lb=dat$lower, ci.ub=dat$upper,
       annotate=TRUE, cex=1.2, at=seq(-2,2,1), digits=c(3,1),
       xlim=c(-5,7), xlab="OR", slab=rownames(dat), atransf=exp)

So, supply log(OR) and the corresponding CI bounds to the function and then use the atransf argument for the back-transformation. In essence, this puts the x-axis on the log-scale.

As for 2:

You will have to compute the point sizes yourself and then supply them to the function via the psize argument.