Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to dodge pointrange ggplots on two levels?

I would like to make a point range plot where points of groups are not stacked on each other. The plot should look like this:enter image description here:

My best attempt to do the dodging is to use a vector in dodge argument:

library(ggplot2)

dat <- structure(list(Treatment = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 
2L, 2L, 2L, 2L, 2L, 2L), .Label = c("A", "B"), class = "factor"), 
    Temp = structure(c(1L, 1L, 1L, 2L, 2L, 2L, 1L, 1L, 1L, 2L, 
    2L, 2L), .Label = c("10", "20"), class = "factor"), Rep = c(1L, 
    2L, 3L, 1L, 2L, 3L, 1L, 2L, 3L, 1L, 2L, 3L), Meas = c(3L, 
    2L, 2L, 2L, 6L, 4L, 4L, 3L, 5L, 1L, 2L, 3L), SD = c(2L, 3L, 
    2L, 2L, 2L, 3L, 2L, 3L, 3L, 3L, 2L, 1L)), .Names = c("Treatment", 
"Temp", "Rep", "Meas", "SD"), row.names = c(NA, -12L), class = "data.frame")

ggplot(dat, aes(x = Treatment, y = Meas, ymin = Meas - SD/2, ymax = Meas + SD/2)) +
geom_linerange(aes(color = Temp), position=position_dodge(width=c(0.6,0.4)), size = 1, alpha = 0.5) +
geom_point(aes(color = Temp, shape = Temp), position=position_dodge(width=c(0.6,0.4)), size = 3) +
theme_bw()

Which leads to a plot shown below. However, all of the points are not dodged and I have to move the dots and error bars in Illustrator to get a plot show above. Is there a way to use dodge argument in ggplot2 on two levels? enter image description here

like image 200
Mikko Avatar asked Mar 18 '13 08:03

Mikko


People also ask

What does position Dodge in R do?

Dodging preserves the vertical position of an geom while adjusting the horizontal position. position_dodge() requires the grouping variable to be be specified in the global or ⁠geom_*⁠ layer.

What does position Dodge do in Ggplot?

position_dodge.Rd. Dodging preserves the vertical position of an geom while adjusting the horizontal position.


2 Answers

Thinking logically, position_dodge is more suitable for bars. It does work with lineranges on one factor level, however on the second level it's hard to define the minimum distance between the lines. Though you can make a numerical distinction between factors and then add proper position for labels.

dat1<-cbind(dat,aux=rep(1,length(dat[,1]))) 
dat1<-within(dat1, {aux = unlist(by(aux,Treatment,cumsum))})
dat1$aux<-dat1$aux+as.numeric(dat1$Treatment)*10
ggplot(dat1, aes( x=aux, y = Meas, ymin = Meas - SD/2, ymax = Meas + SD/2)) +
geom_linerange(aes(color = Temp), size = 1, alpha = 0.5) +geom_point(aes(color = Temp, shape = Temp))+
scale_x_continuous("Treatment",breaks=c(13.5,23.5), labels=c("A","B")) + # here you define coordinates for A and B 
theme_bw()

enter image description here

like image 138
user974514 Avatar answered Oct 13 '22 14:10

user974514


This will not solve the problem with position_dodge() but will be workaround for this problem.

Added new variable x to your original data frame. It contains x coordinates for points/lineranges. Values in data frame should be in order you want to plot them.

dat$x<-c(0.85,0.9,0.95,1.05,1.1,1.15,1.85,1.9,1.95,2.05,2.1,2.15)

Now use this new variable as x values and with scale_x_continuos() set breaks and labels to get A and B on scale.

ggplot(dat, aes(x = x, y = Meas, ymin = Meas - SD/2, ymax = Meas + SD/2)) +
  geom_linerange(aes(color = Temp), size = 1, alpha = 0.5) +
  geom_point(aes(color = Temp, shape = Temp), size = 3) +
  theme_bw()+
  scale_x_continuous("Treatment",breaks=c(1,2),labels=c("A","B"),limits=c(0.5,2.5))
like image 42
Didzis Elferts Avatar answered Oct 13 '22 13:10

Didzis Elferts