Search code examples
rggplot2jitter

how to use geom_segments for jitter


i linked two point using geom_segments in ggplot. it works well for geom_point geom_point are linked but when i use geom_jitter it doesn't gives me the desired results outcome using jitter. I want to see the all points with line between two them. would you please help me how to connect points using geom_jitter? and why points doesn't look parallel?

I modified the code as per suggestion, now points position has been changed points position has been changed

ggplot() +  
geom_point(data = mydata, aes(x = lower, y = lower_p)) + 
geom_point(data = mydata, aes(x = higher, y = higher_p)) + 

geom_segment(aes(x = lower, y = ifelse(lower_p!= higher_p, NA, lower_p), xend = higher, yend = 
higher_p), data = mydata)

Solution

  • Since no example data was posted, I use some dummy data to illustrate some things. Let's set that up:

    df <- data.frame(x = c(1,1,1,2,2),
                     xend = c(2,2,2,3,3),
                     y = c(1,1,1,2,2),
                     yend = c(1,1,1,2,2))
    

    And if we plot this similar to what you posted, we get the following plot wherein points are overplotted 2-3 times:

    ggplot(df) +
      geom_point(aes(x, y), colour = "red") +
      geom_point(aes(xend, yend), colour = "dodgerblue") +
      geom_segment(aes(x = x, y = y, xend = xend, yend = yend))
    

    enter image description here

    Now it might be handy to know that geom_jitter() is shorthand for geom_point(position = "jitter"). Like most positions, you can give the position_jitter() arguments for how you would like the jittering to occur. For example, we might want to jitter only in the y-direction:

    ggplot(df) +
      geom_point(aes(x, y), colour = "red", 
                 position = position_jitter(height = 0.1, width = 0)) +
      geom_point(aes(xend, yend), colour = "dodgerblue",
                 position = position_jitter(height = 0.1, width = 0)) +
      geom_segment(aes(x = x, y = y, xend = xend, yend = yend),
                   position = position_jitter(height = 0.1, width = 0))
    

    enter image description here

    As you can see, this looks horrible since every point is jittered independently from every other point. We can get closer to what we want by setting the seed for the jitter:

    ggplot(df) +
      geom_point(aes(x, y), colour = "red", 
                 position = position_jitter(height = 0.1, width = 0, seed = 1)) +
      geom_point(aes(xend, yend), colour = "dodgerblue",
                 position = position_jitter(height = 0.1, width = 0, seed = 1)) +
      geom_segment(aes(x = x, y = y, xend = xend, yend = yend),
                   position = position_jitter(height = 0.1, width = 0, seed = 1))
    

    enter image description here

    This now handles the left points as expected (since the seed should do the random process identically for every point), but messes up the right points. This happens because these are jittered at the same time as the left points as subsequent numbers instead of parallel to the left points.

    The only reasonable solution seems to be to pre-calculate the jitter and use that such that it is the same for every point:

    set.seed(0)
    df$jit <- runif(nrow(df), -0.05, 0.05)
    
    ggplot(df) +
      geom_point(aes(x, y + jit), colour = "red") +
      geom_point(aes(xend, yend + jit), colour = "dodgerblue") +
      geom_segment(aes(x = x, y = y + jit, xend = xend, yend = yend + jit))
    

    enter image description here