1

I am making a polar violin plot. I would like to add lines and labels to the plot to annotate what each spoke means.

I'm running into two problems.

The first is that when I try to create line segments, if x != xend, then the segments are drawn as curves rather than as lines.

For example:

data.frame(
 x = rnorm(1000), 
  spoke = factor(sample(1:6, 1000, replace=T))
) %>% 
  ggplot(aes(x = spoke, fill=spoke, y = x)) +
  geom_violin() +
  coord_polar() +
  annotate("segment", x=1.1, xend=1.3, y=0, yend=3, color="black", size=0.6) +
  theme_minimal()

The second problem that arises occurs when I try to add an annotation between the last spoke and the first. In this case, the annotation causes the coordinate scale to shift, so that spokes are no longer evenly distributed.

See as here:

data.frame(
  x = rnorm(1000), 
  spoke = factor(sample(1:5, 1000, replace=T))
) %>% 
  ggplot(aes(x = spoke, fill=spoke, y = x)) +
  geom_violin() +
  coord_polar() +
  scale_x_discrete(limits = 1:5) +
  annotate("segment", x=5.9, xend=5.7, y=0, yend=3, color="black", size=0.6) +
  theme_minimal()

Any assistance is greatly appreciated!

(PS: I do understand that there are perceptual issues with plots like these. I have a good reason...)

tjebo
  • 21,977
  • 7
  • 58
  • 94
Bob
  • 1,274
  • 1
  • 13
  • 26
  • 1
    The `segment` is created before "twisting" things to transform into polar coordinates, that's why you see curved lines when annotating with segment. The second occurs because the `coord_polar()` "twists" your x-axis so it wraps every relevant object (note how there is no grid line separating the end and the start) so it naturally distorts the spatial distribution when you add something that increases the relevant range of your x-axis. I can't figure out simple solutions though. – VFreguglia Jul 16 '18 at 19:41
  • @freguglia Yes, thanks, I understand why both problems are occurring, but I haven't been able to find a solution. Please post an answer if you come up with anything! – Bob Jul 16 '18 at 20:13
  • I've simplified the example for posting here. I'm actually using split violins, so using x breaks won't work. Adding a legend isn't the desired goal; the desired goal is to annotate the plot. – Bob Jul 16 '18 at 21:16
  • @tjebo I did reject your edits, because I don't believe they were helpful. x-breaks don't work for split violins for reasons that aren't really relevant to my question, but you're welcome to try it and you'll see what I mean. Regarding the proposal to make a different plot rather than the plot I'm trying to make, I understand your argument, and I'm not saying its without merit, but I'm making this plot for reasons that go beyond what's necessary to discuss in a stack overflow question, and I'm 100% positive that its the plot I genuinely want to make. – Bob Jul 16 '18 at 22:42
  • in this case at least make your code reproducible and add the required packages. – tjebo Jul 16 '18 at 22:44
  • 1
    Have you seen [this question](https://stackoverflow.com/questions/42276773/ggplot-connecting-points-in-polar-coordinates-with-a-straight-line)? If it still works it might give you a starting point. – aosmith Jul 16 '18 at 22:51
  • @aosmith I hadn't seen the question but I had tried that -- it only works if x is constant, i.e., if the segment is along a radial. If `x != xend`, then the segments become curved. (I did include this in the question btw.) – Bob Jul 16 '18 at 23:25
  • @tjebo With all respect, I don't want to keep having an argument with you in the comments to this question. Thank you for offering to help. I'd appreciate if you could give other people a chance without adding too much more static to the comment chain. – Bob Jul 16 '18 at 23:27
  • Meh... this is from three years ago now, but that answer seems more like a suggestion on how an answer could be formulated than an answer itself. – Bob Feb 14 '21 at 17:41

1 Answers1

3

You want an 'generic annotation' as shown here

You basically have to overlay your plots and not use the layer facility, if you don't want to exactly calculate the distance in radians of each x for each y.

With cowplot

require(ggplot2) #again, you should specify your required packages in your question as well
require(cowplot)

my_dat <- data.frame(x = rnorm(1000), 
  spoke = factor(sample(1:6, 1000, replace=T))) 

my_annot <- data.frame(para = c('start','end'), x = c(0,0.4), y = c(0,0.2))
#first point x/y = c(0,0) because this makes positioning easier

When I edited your question and removed the piping - that was not only a matter of good style, but also makes it much easier to then work with your different plots. So - I would suggest you should remove the pipe.

p1 <- ggplot(my_dat, aes(x = spoke, fill=spoke, y = x)) +
  geom_violin() +
  theme_minimal()+
  coord_polar() 

p2 <- ggplot(my_annot) + 
  geom_line(aes(x,y)) +
  coord_cartesian(xlim = c(0,2), ylim =c(0,2)) +
       # the limits change the length of your line too
  theme_void()


ggdraw() +
  draw_plot(p1) +
  draw_plot(p2, x = 0.55, y = 0.6)

Obviously - you can now play around with both length of your line and its position within draw_plot()

enter image description here

tjebo
  • 21,977
  • 7
  • 58
  • 94
  • I think this is on the right track, but when you're making more than one line its not obvious how to do this so that both plots have the same aspect ratio. – Bob Jul 18 '18 at 00:15
  • If you want to edit the answer, the keys to getting it working are using coord_fixed(), setting the limits to be -1, 1 (not 0, 2), and setting the theme on both plots to eliminate any margins. – Bob Jul 18 '18 at 00:59
  • I know this is an old question, but this: https://stackoverflow.com/a/66196752/10624798 answer was just given to a similar question of mine and I think is a lot more scalable. – L Smeets Feb 14 '21 at 17:02
  • Thanks @LSmeets! teunbrand's solutions are almost always better than mine :) (and two years ago, I was even less able than I am now) I will still keep this one as a solution, because although not scalable, it might be sometimes the *easier* solution ;) – tjebo Feb 14 '21 at 17:16
  • @LSmeets I have marked this question as a duplicate though, hopefully it should be closed as such, this will improve the visibility of the link – tjebo Feb 14 '21 at 17:19
  • fair enough, this solution does have the benefit of allowing anything to be added to the plot, not just annotations, but will be fiddly, if you need to add the exact location of a line end. – L Smeets Feb 14 '21 at 17:20
  • The questions aren't duplicates, and neither solution actually works. @tjebo this is really extraordinary - you tried to re-write this question three years ago and I had to ask you to stop commenting. You've now come back three years later to re-argue the same point. – Bob Feb 15 '21 at 20:51
  • @Bob Indeed, when I had this discussion with LSmeets above, I had completely forgotten about this little episode (and I have not looked back into the previous comments, believe it or not). Everything done or said was not meant to be against you, in any way. My honest apologies that apparently this could have been taken differently. Duplicates are not bad - they increase visibility of solutions, linking similar or the same questions. This can help future (re)searchers, a lot. and this is what stack overflow is mostly about, at least in my understanding. Have a good day – tjebo Feb 15 '21 at 23:15