6

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!

2
  • 2
    You'll need to combine the two datasets into a single dataset to make the dodging work Commented Mar 25, 2016 at 20:37
  • 1
    If your real datasets are really so similar, it'd be easy to stack them together and add a group index using something like bind_rows from dplyr. Commented Mar 25, 2016 at 21:21

1 Answer 1

8

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

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

1 Comment

Thanks for the thorough answer! I had thought that the two lines didn't know about each causing the dodging to not work, but thanks for confirming. Unfortunate that there isn't a simpler solution.

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.