1

I have the following data structure:

y <- rep(1:10, 2)
group <- rep(c('a', 'b'), each = 10)
dens <- c(c(seq(from = 0, to = 0.8, by = 0.1), 0),
           c(seq(from = -0, to = -0.8, by = -0.1), 0))
my_dat <- data.frame(group, dens, y, stringsAsFactors = FALSE )

These are calculated density disributions, in order to make a grouped violin plot, such as in
Split violin plot with ggplot2

# Plot 1:
  require(ggplot2)
  ggplot(my_dat, aes(x = dens, y = y, fill = group)) +
  geom_polygon(color = 'black', show.legend = FALSE)

Now this is simplified, because my data contains hundreds of rows for a smooth outline. (However, there is the central vertical line in my case.) I would now like to remove exactly this vertical central line.
(I guess the problem is removing any specified part of the polygon.)

An idea in my example was to overplot this with a vertical line:

#Plot 2
  ggplot(my_dat, aes(x = dens, y = y, fill = group)) +
  geom_polygon(color = 'black', show.legend = FALSE) +
  geom_segment(x = 0, 
               xend = 0, 
               y = min(y) + 0.2, 
               yend = max(y) - 0.2, 
               color = '#00BFC4')

enter image description here

But to get the end of the over plotting segment line correct is tricky. (I have purposefully left the line a bit too short for demonstration)

edit

the groups are not distributed in a symmetrical fashion, although my example strongly suggests so.

Claus Wilke
  • 16,992
  • 7
  • 53
  • 104
tjebo
  • 21,977
  • 7
  • 58
  • 94

2 Answers2

2

You can always just plot another polygon on top

x <- with(my_dat, chull(dens, y))
my_dat2 <- my_dat[c(x, x[1L]), ]

ggplot(my_dat, aes(x = dens, y = y, fill = group)) +
  geom_polygon(show.legend = FALSE) +
  geom_polygon(data = my_dat2, aes(group = 1), size = 1,
               fill = 'transparent',
               # fill = NA,  ## or this
               color = 'black')

enter image description here

rawr
  • 20,481
  • 4
  • 44
  • 78
  • not really. This works only for symmetric groups. The whole point of separating the two groups is that they are *not* symmetrical. Should have specified this better. Will add this to the question – tjebo May 10 '18 at 00:12
  • 1
    that seems irrelevant to me, can you amend your example – rawr May 10 '18 at 00:19
  • OK you were right! Sorry! It is indeed irrelevant. Oops, I obviously have not immediately understood your code (did not know `chull`, and I have to get my head around your use of `with`...). Cool. many thanks. – tjebo May 10 '18 at 00:27
  • great! but I think this solution may not work if there are concave points along your perimeter in which case the convex hull would not lay on the perimeter – rawr May 10 '18 at 01:04
  • Sorry to come back to you again. I was on a run and have not checked it on my real data. It doesn't work with it. I guess I have to make another example, because it does not work with more complex polygons because (I assume) `chull` only creates certain 'edge points'.... Can't do this today, will do tomorrow. Nevertheless, I leave the answer accepted because it answers my specific question – tjebo May 10 '18 at 01:41
1

I think the simpler solution is to first draw all the outlines and then all the filled areas. This should work for any arbitrary polygon shapes.

y <- rep(1:10, 2)
group <- rep(c('a', 'b'), each = 10)
dens <- c(c(seq(from = 0, to = 0.8, by = 0.1), 0),
         c(seq(from = -0, to = -0.8, by = -0.1), 0))
my_dat <- data.frame(group, dens, y, stringsAsFactors = FALSE )

require(ggplot2)
ggplot(my_dat, aes(x = dens, y = y)) +
  geom_polygon(color = 'black', fill = NA, size = 2) +
  geom_polygon(aes(fill = group), color = NA)

enter image description here

Claus Wilke
  • 16,992
  • 7
  • 53
  • 104
  • that's a very neat twist to swap the group mapping into the respective geom calls. Now, you couldn't know that, because I hadn't put this into the question (because I hadn't realised that this would be of importance in this moment)... but I am using alpha for my fill, so the underlying plot still 'shines through'... – tjebo May 10 '18 at 05:50