Home > Mobile >  How to use position_dodge with 2 levels of groupings in ggplot2
How to use position_dodge with 2 levels of groupings in ggplot2

Time:07-14

I would like to group a series of lines by 2 factors using group = interaction in ggplot. Here is some sample code:

set.seed(123)
N <- 18
means <- rnorm(N,0,1)
ses <- rexp(N,2)
upper<- means qnorm(0.975)*ses
lower<- means qnorm(0.025)*ses
fruit <- rep(c("Apples","Bananas","Pears"), each=6)
size <- rep(rep(c("Small","Medium","Big"), each=2),3)
GMO <- rep(c("Yes","No"), 9)
d<- data.frame(means,upper,lower,fruit,size,GMO)


ggplot(data=d,
       aes(x = fruit,y = means, ymin = lower, ymax = upper, col=size,linetype=GMO,group=interaction(GMO, size))) 
  geom_hline(aes(fill=size),yintercept =1, linetype=2) 
  xlab('labels')  ylab("Parameter estimates (95% Confidence Interval)") 
  geom_pointrange(position=position_dodge(width = 0.6))  
  scale_x_discrete(name="Fruits") 
  coord_flip()-> fplot
dev.new()
fplot

Here's a link to the resulting graph: https://i.stack.imgur.com/5YF4F.png

I would like to bring the same coloured lines for each of the three groups closer together. In other words I would like the lines to cluster not only by the 'Fruit' variable but also the 'Size' variable for each of the fruits. poisition_dodge seems to only work for one of the interacting groups.

Thanks for your advice.

CodePudding user response:

As far as I know that is not possible with position_dodge, i.e. it dodges according to the categories of the group aes. And it does not matter whether you map one variable on the group aes or an interaction of two or more. The groups are simply placed equidistant from one another.

One option to achieve your desired result would be to use the "facets that don't look like facets" trick which means faceting by fruit, mapping size on x and afterwards using theme options to get rid of the facet look plus some tweaking of the x scale:

set.seed(123)
N <- 18
means <- rnorm(N, 0, 1)
ses <- rexp(N, 2)
upper <- means   qnorm(0.975) * ses
lower <- means   qnorm(0.025) * ses
fruit <- rep(c("Apples", "Bananas", "Pears"), each = 6)
size <- rep(rep(c("Small", "Medium", "Big"), each = 2), 3)
GMO <- rep(c("Yes", "No"), 9)
d <- data.frame(means, upper, lower, fruit, size, GMO)


library(ggplot2)

ggplot(data = d, aes(x = size, y = means, ymin = lower, ymax = upper, col = size, linetype = GMO, group = GMO))  
  geom_hline(yintercept = 1, linetype = 2)  
  xlab("labels")  
  ylab("Parameter estimates (95% Confidence Interval)")  
  geom_pointrange(position = position_dodge(width = 0.6))  
  scale_x_discrete(name = "Fruits", breaks = "Medium", labels = NULL, expand = c(0, 1))  
  coord_flip()  
  facet_grid(fruit ~ ., switch = "y")  
  theme(strip.placement = "outside", 
        strip.background.y = element_blank(),
        strip.text.y.left = element_text(angle = 0),
        panel.spacing.y = unit(0, "pt"))

CodePudding user response:

Maybe you want to facet_wrap your size variable:

set.seed(123)
N <- 18
means <- rnorm(N,0,1)
ses <- rexp(N,2)
upper<- means qnorm(0.975)*ses
lower<- means qnorm(0.025)*ses
fruit <- rep(c("Apples","Bananas","Pears"), each=6)
size <- rep(rep(c("Small","Medium","Big"), each=2),3)
GMO <- rep(c("Yes","No"), 9)
d<- data.frame(means,upper,lower,fruit,size,GMO)

library(ggplot2)
#> Warning: package 'ggplot2' was built under R version 4.1.2
ggplot(data=d,
       aes(x = fruit,y = means, ymin = lower, ymax = upper, col=size,linetype=GMO,group=interaction(GMO, size))) 
  geom_hline(aes(fill=size),yintercept =1, linetype=2) 
  xlab('labels')  ylab("Parameter estimates (95% Confidence Interval)") 
  geom_pointrange(position=position_dodge(width = 0.6))  
  scale_x_discrete(name="Fruits") 
  coord_flip()  
  facet_wrap(~size)-> fplot
#> Warning: geom_hline(): Ignoring `mapping` because `yintercept` was provided.
fplot

Created on 2022-07-13 by the reprex package (v2.0.1)

  • Related