Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

R - ggplot dodging geom_lines

Tags:

plot

r

ggplot2

This has been something I've been experimenting with to find a fix for a while, but basically I was wondering if there is a quick way to "dodge" lineplots for two different data sets in ggplot2.

My code is currently:

#Example data
id <- c("A","A")
var <- c(1,10)
id_num <- c(1,1)
df1 <- data.frame(id,var,id_num)

id <- c("A","A")
var <- c(1,15)
id_num <- c(0.9,0.9)
df2 <- data.frame(id,var,id_num)


#Attempted plot
dodge <- position_dodge(width=0.5)
p<- ggplot(data= df1, aes(x=var, y=id))  +
  geom_line(aes(colour="Group 1"),position="dodge") + 
  geom_line(data= df2,aes(x=var, y=id,colour="Group 2"),position="dodge") +
  scale_color_manual("",values=c("salmon","skyblue2"))
p

Which produces:

enter image description here

Here the "Group 2" line is hiding all of the "Group 1" line which is not what I want. Instead, I want the "Group 2" line to be below the "Group 1" line. I've looked around and found this previous post: ggplot2 offset scatterplot points but I can't seem to adapt the code to get two geom_lines to dodge each other when using separate data frames.

I've been converting my y-variables to numeric and slightly offsetting them to get the desired output, but I was wondering if there was a faster/easier way to get the same result using the dodge functionality of ggplot or something else.

My work around code is simply:

p<- ggplot(data= df1, aes(x=var, y=id_num))  +
  geom_line(aes(colour="Group 1")) + 
  geom_line(data= df2,aes(x=var, y=id_num,colour="Group 2")) +
  scale_color_manual("",values=c("salmon","skyblue2")) + 
  scale_y_continuous(lim=c(0,1))
p

Giving me my desired output of:

Desired output:

Desired output

The numeric approach can be a little cumbersome when I try to expand it to fit my actual data. I have to convert my y-values to factors, change them to numeric and then merge the values onto the second data set, so a quicker way would be preferable. Thanks in advance for your help!

like image 618
Mike H. Avatar asked Mar 25 '16 20:03

Mike H.


1 Answers

You have actually two issues here:

  1. If the two lines are plotted using two layers of geom_line() (because you have two data frames), then each line "does not know" about the other. Therefore, they can not dodge each other.

  2. position_dodge() is used to dodge in horizontal direction. The standard example is a bar plot, where you place various bars next to each other (instead of on top of each other). However, you want to dodge in vertical direction.

Issue 1 is solved by combining the data frames into one as follows:

library(dplyr)
df_all <- bind_rows(Group1 = df1, Group2 = df2, .id = "group")
df_all
## Source: local data frame [4 x 4]
## 
##    group     id   var id_num
##    (chr) (fctr) (dbl)  (dbl)
## 1 Group1      A     1    1.0
## 2 Group1      A    10    1.0
## 3 Group2      A     1    0.9
## 4 Group2      A    15    0.9

Note how setting .id = "Group" lets bind_rows() create a column group with the labels taken from the names that were used together with df1 and df2.

You can then plot both lines with a single geom_line():

library(ggplot2)
ggplot(data = df_all, aes(x=var, y=id, colour = group))  +
   geom_line(position = position_dodge(width = 0.5)) +
   scale_color_manual("",values=c("salmon","skyblue2"))

enter image description here

I also used position_dodge() to show you issue 2 explicitly. If you look closely, you can see the red line stick out a little on the left side. This is the consequence of the two lines dodging each other (not very successfully) in vertical direction.

You can solve issue 2 by exchanging x and y coordinates. In that situation, dodging horizontally is the right thing to do:

ggplot(data = df_all, aes(y=var, x=id, colour = group))  +
   geom_line(position = position_dodge(width = 0.5)) +
   scale_color_manual("",values=c("salmon","skyblue2"))

enter image description here

The last step is then to use coord_flip() to get the desired plot:

ggplot(data = df_all, aes(y=var, x=id, colour = group))  +
   geom_line(position = position_dodge(width = 0.5)) +
   scale_color_manual("",values=c("salmon","skyblue2")) +
   coord_flip()

enter image description here

like image 63
Stibu Avatar answered Oct 22 '22 13:10

Stibu