2

By default, the neighboring violins will touch each other at the widest point if the widest point occurs at the same height. I would like to make my violin plots wider so that they overlap each other. Basically, something more similar to a ridge plot:

ridge plot

Is that possible with geom_violin?

I saw the width parameter, but if I set it higher than 1, I get these warnings, which makes me think that may not be the most appropriate approach:

Warning: position_dodge requires non-overlapping x intervals
Z.Lin
  • 28,055
  • 6
  • 54
  • 94
burger
  • 5,683
  • 9
  • 40
  • 63

1 Answers1

3

I don't think geom_violin is meant to do this by design, but we can hack it with some effort.

Illustration using the diamonds dataset from ggplot2:

# normal violin plot
p1 <- diamonds %>%
  ggplot(aes(color, depth)) +
  geom_violin()

# overlapping violin plot
p2 <- diamonds %>%
  rename(x.label = color) %>% # rename the x-variable here; 
                              # rest of the code need not be changed
  mutate(x = as.numeric(factor(x.label)) / 2) %>%
  ggplot(aes(x = x, y = depth, group = x)) +

  # plot violins in two separate layers, such that neighbouring x values are
  # never plotted in the same layer & there's no overlap WITHIN each layer
  geom_violin(data = . %>% filter(x %% 1 != 0)) +
  geom_violin(data = . %>% filter(x %% 1 == 0)) +

  # add label for each violin near the bottom of the chart
  geom_text(aes(y = min(depth), label = x.label), vjust = 2, check_overlap = TRUE) +

  # hide x-axis labels as they are irrelevant now
  theme(axis.text.x = element_blank(),
        axis.ticks.x = element_blank())

gridExtra::grid.arrange(
  p1 + ggtitle("Normal violins"),
  p2 + ggtitle("Overlapping violins"),
  nrow = 2
)

plot

Z.Lin
  • 28,055
  • 6
  • 54
  • 94