30

I did something like this with my data, but despite the transparency the segments are hard to visualise (my data has lot less number of segments than the example below) to see their beginning and end.

require(ggplot2)
ggplot(iris, aes(x = Petal.Length, xend = Petal.Width,
                 y = factor(Species), yend = factor(Species),
                 size = Sepal.Length)) +
    geom_segment(alpha = 0.05) + 
    geom_point(aes(shape = Species))

Came across this solution, but the lines are criss-crossed. Is there a way to make the jitter produce parallell lines with the points at the tips? I have tried position_dodge instead of position_jitter, but it requires ymax. Can ymax be integrated at all for use with geom_segment?

ggplot(iris, aes(x = Petal.Length, xend = Petal.Width,
                 y = factor(Species), yend = factor(Species))) +
    geom_segment(position = position_jitter(height = 0.25))+
    geom_point(aes(size = Sepal.Length, shape = Species))
Henrik
  • 65,555
  • 14
  • 143
  • 159
Anto
  • 1,189
  • 10
  • 16

3 Answers3

29

As far as I know, geom_segment does not allow jittering nor dodging. You can add jittering to the relevant variable in the data frame, then plot the jittered variable. In your example, the factor is converted to numeric, then the labels for the levels of the factor are added to the axis using scale_y_continuous.

library(ggplot2)
iris$JitterSpecies <- ave(as.numeric(iris$Species), iris$Species, 
   FUN = function(x) x + rnorm(length(x), sd = .1))

ggplot(iris, aes(x = Petal.Length, xend = Petal.Width,
                 y = JitterSpecies, yend = JitterSpecies)) +
    geom_segment()+
    geom_point(aes(size=Sepal.Length, shape=Species)) +
    scale_y_continuous("Species", breaks = c(1,2,3), labels = levels(iris$Species))

enter image description here

But it seems geom_linerange allows dodging.

ggplot(iris, aes(y = Petal.Length, ymin = Petal.Width,
                 x = Species, ymax = Petal.Length, group = row.names(iris))) +
       geom_point(position = position_dodge(.5)) +
     geom_linerange(position = position_dodge(.5)) +
     coord_flip()

enter image description here

Sandy Muspratt
  • 31,719
  • 12
  • 116
  • 122
  • Many thx! Both images are like the one I wanted. Will try it out. – Anto Feb 21 '14 at 09:11
  • Your first solution worked for me. With my data, the length of the segments represent time durations and when I use geom_linerange with facetting(scales='free'), the axis still show the whole range for the y-axis and just the range for each panel - probably because of the ymin and ymax settings. So, went in for the geom_segment. :) – Anto Feb 24 '14 at 09:54
  • 5
    @Sandy Muspratt Do you know of any documentation for the dodging behaviour of `geom_segment` ("As far as I know, `geom_segment` does not allow jittering nor dodging")? I have seen [**this post**](https://groups.google.com/forum/#!searchin/ggplot2/geom_segment$20position_dodge/ggplot2/iWojkpMicRY/ZMR75OOpHBQJ) on _vertical_ dodging, but I have a similar problem for horizontal dodging: `y` is dodged, but `yend` is not. It's slightly puzzling that `geom_segment` has a `position` argument if it's not working anyway... – Henrik Feb 10 '15 at 07:43
  • Almost a decade later, see my updated answer for `ggplot2 3.4.2`. https://stackoverflow.com/a/76076569/4205652 – Richard Erickson Apr 21 '23 at 20:42
2

Updated for ggplot2 version 3.4.2 and to build upon another short answer:

You may now use position = position_dodge2(width = 0.1). For example:

ggplot(iris, aes(x = Species,
                 ymin = Petal.Length,
                 ymax = Petal.Width)) +
  geom_linerange(position = position_dodge2(width = 0.5)) +
  coord_flip() +
  theme_bw()

Will produce this figure:Example ggplot2 output.

Note that ggplot2 only allows geom_linerange() for the y-axis, hence the use of coord_flip().

Richard Erickson
  • 2,568
  • 8
  • 26
  • 39
1

The position argument of geom_segment might be helpful for you, see Slightly change geom_segment's position of x only, but keep position of xend constant

LuleSa
  • 75
  • 7