Plotting overlapping lines in R
2
0
Entering edit mode
2.8 years ago
anna ▴ 20

I am trying to plot in R my analyses, but in the plot I have overlapping lines.

How could I set an offset for the lines?

Thank you!

Here is my code and the plot:

mu <- 1.25e-8
gen <- 30
EA_S<-read.table("coal_output_E_S.final.txt", header=TRUE)
EA_WA<-read.table("coal_output_E_W.final.txt", header=TRUE)
S_CA<-read.table("cross_coal_S_CA.final.txt", header=TRUE)
S_WA<-read.table("cross_coal_S_WA.final.txt", header=TRUE)
WA_CA<-read.table("cross_coal_WA_CA.final.txt", header=TRUE)
EA_CA<-read.table("cross_coal_EA_CA.final.txt", header=TRUE)
plot(S_CA$left_time_boundary/mu*gen, 2 * S_CA$lambda_01 / (S_CA$lambda_00 + S_CA$lambda_11), xlim=c(1000,10000),ylim=c(0,1), type="n", xlab="Years ago", ylab="relative cross-coalescence rate")
lines(EA_S$left_time_boundary/mu*gen, 2 * EA_S$lambda_01 / (EA_S$lambda_00 + EA_S$lambda_11), type="s", col="red")
lines(S_CA$left_time_boundary/mu*gen, 2 * S_CA$lambda_01 / (S_CA$lambda_00 + S_CA$lambda_11), type="s", col="blue")
lines(S_WA$left_time_boundary/mu*gen, 2 * S_WA$lambda_01 / (S_WA$lambda_00 + S_WA$lambda_11), type="s", col="green")
lines(WA_CA$left_time_boundary/mu*gen, 2 * WA_CA$lambda_01 / (WA_CA$lambda_00 + WA_CA$lambda_11), type="s", col="grey")
lines(EA_CA$left_time_boundary/mu*gen, 2 * EA_CA$lambda_01 / (EA_CA$lambda_00 + EA_CA$lambda_11), type="s", col="orange")
lines(EA_WA$left_time_boundary/mu*gen, 2 * EA_WA$lambda_01 / (EA_WA$lambda_00 + EA_WA$lambda_11), type="s", col="violet")
legend("topright",legend=c("EA-S", "S-CA", "S-WA", "WA-CA", "EA-CA", "EA-WA"), col=c("red", "blue", "green", "grey", "orange", "violet"), lty=c(1,1))

enter image description here

plot overlap R • 12k views
ADD COMMENT
3
Entering edit mode

Possible ggplot2 solution using position_dodge:

ADD REPLY
1
Entering edit mode

Fixing overplotting with lines is not straightforward. If possible, you might select a better way to get your point across. However, you could consider adding some custom jitter to the line values, as long as you make it absolutely clear that the values have been jittered for display purposes. There's no automatic way to set an offset, because this involves changing the data. If you're making a custom figure, and want to stick to the format above, you could consider adding custom annotations to indicate where overplotting is occurring (e.g. for one line, indicate all labels represented under that line). On the other hand, do you have to use lines? Can you use points instead? A jittered point approach might be easier to distinguish and explain.

ADD REPLY
1
Entering edit mode

Difficult to show so many overlapping lines, unless each sample is represented by individual line shapes and colors, but that would be confusing. You can try showing them in a different plane (3d).

ADD REPLY
0
Entering edit mode

Thank you all! Very helpful!

ADD REPLY
2
Entering edit mode
2.8 years ago
M__ ▴ 200

ggplot2 and use dashed lines

ADD COMMENT
3
Entering edit mode

A more explanatory answer would be helpful. Does ggplot have some special magic switch for overplotting? Lines with the same values will be plotted on top of each other, just as in base graphics. Lines with dashes plotted on top of each other will be indistinguishable.

ADD REPLY
1
Entering edit mode

These are good suggestions here and dashing together position_dodge may work. Another angle is ggplot2's position_jitter

 (ggplot2 code) ... + position_jitter()

This will work but you will need discrete time intervals on the x-axis. At present the graph uses a continuous variable so it will not work. To be honest there is only a single point on the x-axis so I don't see the issue here, the vertical lines will simply be scattered on the discrete time interval close to 4000 YA and then converge at around 0.96

The linked image looks messy, but in the OPs case will look cool because there are not many points involved and by gauging the size of the time intervals they will be able to control the scattering accurately.

position jitter example

ADD REPLY
1
Entering edit mode

Thank you!

ADD REPLY
1
Entering edit mode

Finally, if you made a discrete interval on the y-axis, as well as the x-axis and added + position_jitter(), then you would have the affect sought where each line being visible throughout the the entirety of the plot.

However, I am not certain that position_jitter() operates on the y-axis ,

ADD REPLY
1
Entering edit mode

Yes, as @zx8754 suggested, position dodge is the magic sauce in ggplot, which will move the lines slightly:

library(ggplot2)
df <- data.frame(time=c(1:10,1:10,1:10), signal=c(sin(1:10), sin(1:10), cos(1:10)), 
                 sample=c(rep(c(letters[1:3]), each=10)))

ggplot(df, aes(x=time, y=signal, color=sample)) + geom_line(position = position_dodge(width = 0.2))

enter image description here

ADD REPLY
1
Entering edit mode
2.8 years ago
Dunois ★ 2.8k

Two solutions I can think of:

  1. Try trimming the X-axis range to something smaller, and hope the lines get a little bit more distributed in this dimension. There's nothing you can do about the Y-axis. This solution goes out of the window if you cannot change the X-axis limits at all.

  2. Use ggplot2::facet_grid() or ggplot2::facet_wrap() to split each curve into its own panel, and present the entire thing as a multi-panel plot. You only have 6 curves worth of data, so that's a 2x3 or 3x2 (or whatever will you) panels. IMHO this is the right way to deal with this situation.

Here's a small working example for facet_wrap() with somewhat similar data:

#Generating some toy data.
mysig <- function(x){
  data.frame(x = x, y = 1/ ( 1+exp(x) ), stringsAsFactors = FALSE)
}

inps <- rep(seq(-10, 10), 6)

df <- mysig(inps)

df$samp <- rep(sample(letters, size = 6, replace = FALSE), each = 21)

#--------

#Plotting.
library(ggplot2)

#Without facet wrap.
ggplot(data = df, aes(x = x, y = y, color = samp)) + 
  geom_line()

#With facet wrap.
ggplot(data = df, aes(x = x, y = y, color = samp)) + 
  geom_line() + 
  facet_wrap(~samp)

#--------

The unfaceted plot looks like this:

ggnofacet

With paneling, it would look like this instead:

ggfacet

I'd say this is an acceptable compromise.

ADD COMMENT

Login before adding your answer.

Traffic: 2295 users visited in the last hour
Help About
FAQ
Access RSS
API
Stats

Use of this site constitutes acceptance of our User Agreement and Privacy Policy.

Powered by the version 2.3.6