1

I created a graph showing the effect size and confidence intervals. I would like to put on the right side of this graph (second y-axis) exact text information about "ES" and "CI" in the form: -0.07 [-1.16, 0.99], which means: ES [+95 CI, -95CI]. I can't handle it. Could I please help? Such a chart can certainly be useful to someone else. Of course, it would be nice to keep those vertical gray lines next to the variable names ... I struggled to draw it in paint :-)

library(ggplot2)

my_data <- data.frame(
  index = c(1L, 1L, 1L, 3L, 3L, 3L, 5L, 5L, 5L),
  es = c(0.14, -0.18, -0.46, -0.07, 0.42, 0.51, 0.56, 0.24, -0.35),
  lower_CI = c(-0.92, -1.29, -1.63, -1.16, -0.59, -0.5, -0.44, -0.79, -1.5),
  upper_CI = c(1.23, 0.86, 0.55, 0.99, 1.58, 1.69, 1.75, 1.36, 0.67),
  varname = as.factor(c("Crawl Legs (s)","Crawl Legs (s)","Crawl Legs (s)",
                        "Crawl Arms (s)","Crawl Arms (s)","Crawl Arms (s)",
                        "Front Crawl (s)","Front Crawl (s)","Front Crawl (s)")),
  period = as.factor(c("TP/DP","TP/RP","DP/RP","TP/DP","TP/RP","DP/RP","TP/DP","TP/RP","DP/RP"))
)
ggplot(my_data, aes(y = varname, x = es, color = period, fill = period)) +
  geom_point(shape = 21, size = 2, position=position_dodge(width = 0.5)) +  
  geom_errorbar(aes(xmin = lower_CI, xmax = upper_CI), width = 0.2, position=position_dodge(width = 0.5)) +
  scale_color_manual("period", values=c("#0073C2FF", "#EFC000FF", "#CD534CFF")) +
  geom_vline(xintercept = c(-2, -2, -1.2, -.6, -.2, 0, .2, .6, 1.2, 2, 2),
             color = c("grey", "grey", "grey", "grey", "grey", "black", "grey", "grey", "grey", "grey", "grey"), linetype = c("dashed", "dashed","dashed", "dashed", "dashed", "solid", "dashed","dashed", "dashed", "dashed", "dashed"),
             cex = c(.5, .5, .5, .5, .5, 1, .5, .5, .5, .5, .5), alpha = 0.5) +
  scale_x_continuous(limits=c(-2.8, 2.8), breaks=c(-2, -1.2, -.6, -.2, .2, .6, 1.2, 2), labels = unicode_minus) +
  scale_fill_manual(values = c("#0073C2FF", "#EFC000FF", "#CD534CFF")) +
  xlab("Standardized mean difference (±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.y = element_blank(),
        axis.line.x = element_blank(),
        axis.ticks.y = element_line(size = 18, colour = "grey"),
        axis.ticks.x = element_blank(),
        axis.text.y = element_text(size = 12, colour = "black"),
        axis.text.x.bottom = element_text(size = 10, colour = "black"),
        axis.title.x = element_text(size = 12, colour = "black", vjust = -0.75),
        legend.position = c(0.08, 0.9), legend.title = element_blank(),
        legend.text = element_text(color = "black", size = 11))

enter image description here

0

1 Answer 1

2

You can use a geom_text layer and some segment annotations:

ggplot(my_data, aes(y = varname, x = es, color = period, fill = period)) +
  geom_point(shape = 21, size = 2, position=position_dodge(width = 0.5)) +  
  geom_errorbar(aes(xmin = lower_CI, xmax = upper_CI), width = 0.2, 
                position=position_dodge(width = 0.5)) +
  scale_color_manual("period", values=c("#0073C2FF", "#EFC000FF", "#CD534CFF")) +
  geom_vline(xintercept = c(-2, -2, -1.2, -.6, -.2, 0, .2, .6, 1.2, 2, 2),
             color = c(rep("grey", 5), "black", rep("grey", 5)),
             linetype = c(rep("dashed", 5), "solid", rep("dashed", 5)),
             cex = c(rep(0.5, 5), 1, rep(0.5, 5)), alpha = 0.5) +
  geom_text(aes(x = 2.3, label = paste0(es, " [", lower_CI, ", ", upper_CI, "]"),
                group = period), color = "black",
            position = position_dodge(width = 0.5), hjust = 0) +
  annotate("segment", x = rep(2.1, 3), xend = rep(2.1,  3),
           y = 0.75 + 0:2, yend = 0.25 + 1:3, size = 1.5, color = "gray") +
  scale_x_continuous(limits = c(-2.8, 3), 
                     breaks = c(-2, -1.2, -.6, -.2, .2, .6, 1.2, 2)) +
  scale_fill_manual(values = c("#0073C2FF", "#EFC000FF", "#CD534CFF")) +
  labs(x = "Standardized mean difference (±95% CI)", y = NULL) + 
  theme_minimal() +
  theme(panel.grid = element_blank(), 
        axis.ticks.y = element_line(size = 18, colour = "grey"),
        axis.ticks.x = element_blank(),
        axis.text.y = element_text(size = 12, colour = "black"),
        axis.text.x.bottom = element_text(size = 10, colour = "black"),
        axis.title.x = element_text(size = 12, colour = "black", vjust = -0.75),
        legend.position = c(0.08, 0.9), legend.title = element_blank(),
        legend.text = element_text(color = "black", size = 11))

enter image description here

Sign up to request clarification or add additional context in comments.

3 Comments

Thank you very much for your help and for optimizing the code in several places. I am trying to understand this part of the code: 'annotate("segment"...', especially the settings for y = 0.75 + 0: 2, yend = 0.25 + 1: 3. I don't know what settings I could make e.g. for 6 variables?
Every group on the y axis is centred on an integer value starting at 1, with the range of the clusters being 0.25 either side (since the dodge width is 0.5). For 6 values, you would want y = 1:6 - 0.25 and yend = 1:6 + 0.25
y = 0.75 + 0:5, yend = 0.25 + 1:6

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.