This section contains the setup and the various utility functions used throughout.
Libraries used:
library(data.table)
library(ggplot2)
library(grid)
library(gridExtra)
library(ggrepel)
Some fake data.
The N
correspond to the number in the subgroup that were allocated to each group.
The other variables should be self-evident.
dat <- data.table(
idx = 1:11,
label = c(
"Age (<50)",
"Age (>=50)",
"Sex (F)",
"Sex (M)",
"Comorbidity (N)",
"Comorbidity (Y)",
"Hypertension (N)",
"Hypertension (Y)",
"O2 reqd (N)",
"O2 reqd (Y)",
"Overall"
),
N_ARB = c(198,186,136,248,279,105,297,87,279,105,384),
N_Control = c(195,187,140,242,265,117,264,118,276,106,382),
OR = exp(c(0.433,0.386,0.332,0.457,
0.433,0.359,0.361,
0.529,0.406,0.424, 0.411)),
LL = exp(c(-0.056,-0.103,-0.289,
0.021,-0.006,-0.236,
-0.123,0.033,-0.061,-0.045,0.023)),
UL = exp(c(0.941,0.844,0.830,0.926,0.892,
0.855,0.801,1.206,0.867,0.903,0.801))
)
dat[, CI:= sprintf("%.2f, %.2f", LL, UL)]
dat[, shape:= 18]
# toying with the option of specifying a different shape for overall
dat[label == "Overall", shape:= 18]
p1 <- ggplot(dat, aes(y = idx, x = OR)) +
geom_errorbarh(aes(xmin = LL, xmax = UL), height = 0.25) +
geom_point(aes(shape = shape), size = 3) +
# When using integers to indicate shapes through aesthetics, you need
# to include this otherwise you will get an error.
scale_shape_identity() +
# scale_color_manual(values = c("A" = "black", "B" = "white")) +
geom_vline(xintercept = 1, linetype = "dashed", cex = 0.25) +
scale_y_continuous(name = "", breaks=1:11, labels = dat$label, trans = "reverse") +
xlab("Odds Ratio (95% CI)") +
ylab(" ") +
theme_bw() +
theme(panel.border = element_blank(),
panel.background = element_blank(),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
axis.line = element_line(colour = "black"),
axis.text.y = element_text(size = 10, colour = "black"),
axis.text.x.bottom = element_text(size = 10, colour = "black"),
axis.title.x = element_text(size = 10, colour = "black"),
legend.position = "none")
p1
The code that follows sets up the text elements.
## Create the table-base pallete
tbl1 <- ggplot(dat, aes(y=label)) +
ylab(NULL) + xlab(" ") +
theme(plot.title = element_text(hjust = 0.5, size=10),
## This is used to help with alignment
axis.text.x = element_text(color="white", hjust = -3, size = 25),
axis.line = element_blank(),
axis.text.y = element_blank(),
axis.ticks = element_blank(),
axis.title.y = element_blank(),
legend.position = "none",
panel.background = element_blank(),
panel.border = element_blank(),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
plot.background = element_blank())
## OR point estimate table
txtscale <- 3.5
p2 <- tbl1 +
labs(title = "space") +
## decimal places
geom_text(aes(
y = rev(idx), x = 1,
label = sprintf("%0.2f", round(OR, digits = 1))), size = txtscale) +
ggtitle("OR")
## 95% CI table
p3 <- tbl1 +
geom_text(aes(y = rev(idx), x = 1, label = CI), size = txtscale) +
ggtitle("95% CI")
## 95% CI table
p4 <- tbl1 +
geom_text(aes(y = rev(idx), x = 1, label = N_ARB), size = txtscale) +
ggtitle("N (ARB)")
p5 <- tbl1 +
geom_text(aes(y = rev(idx), x = 1, label = N_Control), size = txtscale) +
ggtitle("N (Control)")
And now, using the grid
package allows us to lay out the plots onto an arbitrary panel.
pp1 <- ggplotGrob(p1)
pp2 <- ggplotGrob(p2)
pp3 <- ggplotGrob(p3)
pp4 <- ggplotGrob(p4)
pp5 <- ggplotGrob(p5)
grid::grid.newpage()
vp <- viewport(x = 0.0, y = 0,
width = 0.5, height = 1,
just = c("left", "bottom"))
pushViewport(vp)
grid.draw(pp1)
popViewport()
vp <- viewport(x = 0.5, y = 0.0,
width = 0.1, height = 1,
just = c("left", "bottom"))
pushViewport(vp)
grid.draw(pp2)
popViewport()
vp <- viewport(x = 0.6, y = 0.0,
width = 0.2, height = 1,
just = c("left", "bottom"))
pushViewport(vp)
grid.draw(pp3)
popViewport()
vp <- viewport(x = 0.8, y = 0.0,
width = 0.1, height = 1,
just = c("left", "bottom"))
pushViewport(vp)
grid.draw(pp4)
popViewport()
vp <- viewport(x = 0.9, y = 0.0,
width = 0.1, height = 1,
just = c("left", "bottom"))
pushViewport(vp)
grid.draw(pp5)
popViewport()