Zhili Qiao
Zhili Qiao

Reputation: 109

Limiting vertical line length in R ggplot2

I am trying to draw a forest plot with different groups. The code I'm using looks like the following:

d = data.frame(Estimate = c(1.8,1.9,2.1,2.4,2.7,2.5), 
               Group = rep(c('Group A', 'Group B'), each = 3),
               Method = rep(c('Method 1', 'Method 2', 'Method 3'), 2))
d$Lower = d$Estimate - 0.3
d$Upper = d$Estimate + 0.3
ggplot(data = d, aes(y = Group, x = Estimate, xmin = Lower, xmax = Upper, color = Method)) + 
  geom_point(size = 2, position=position_dodge(width = 0.5)) + 
  geom_linerange(position=position_dodge(width = 0.5)) + 
  geom_vline(xintercept = c(2, 2.5), linetype = "dashed")

And the resulting plot: enter image description here

The vertical lines (2, 2.5) are the true group means. I want to limit these vertical lines to be within each group (i.e., the first one from bottom to the middle, the second one middle to top). Anyone know how to do this?

I've tried geom_segment() function but I think it requires a numerical y input, while it's a factor here.

Upvotes: 3

Views: 1022

Answers (1)

Allan Cameron
Allan Cameron

Reputation: 173793

Factors plotted on an axis are "really" numeric, but with labels added, so you can go ahead and add numeric segments:

ggplot(data = d, aes(y = Group, x = Estimate, xmin = Lower, xmax = Upper, 
                     color = Method)) + 
  geom_point(size = 2, position=position_dodge(width = 0.5)) + 
  geom_linerange(position=position_dodge(width = 0.5)) + 
  geom_segment(data = data.frame(y = c(0.67, 1.67), x = c(2, 2.5), 
                                 xend = c(2, 2.5),  yend = c(1.33, 2.33)), 
               aes(x, y, xend = xend, yend = yend),
               inherit.aes = FALSE, linetype = 2) 

enter image description here

Or, with a few tweaks:

ggplot(data = d, aes(y = Group, x = Estimate, xmin = Lower, xmax = Upper, 
                     color = Method)) + 
  geom_linerange(position=position_dodge(width = 0.5), size = 1) + 
  geom_point(size = 3, position=position_dodge(width = 0.5), shape = 21,
             fill = "white") + 
  geom_segment(data = data.frame(y = c(0.67, 1.67), x = c(2, 2.5), 
                                 xend = c(2, 2.5),  yend = c(1.33, 2.33)), 
               aes(x, y, xend = xend, yend = yend),
               inherit.aes = FALSE, linetype = 2) +
  annotate("text", c(2, 2.5), c(1.5, 2.5), size = 6,
           label = c("Group mean = 2", "Group mean = 2.5")) +
  theme_minimal(base_size = 20) +
  scale_color_brewer(palette = "Set1")

enter image description here

Upvotes: 4

Related Questions