1

Once points in a geom_violin are distributed via geom_sina and then labelled via geom_label_repel or even geom_label, the line points to the midline of the x-axis category. Is there a way to have geom_label_repel or even geom_label know where the point is after geom_sina?

Example:

library(dplyr)
library(ggforce)
library(ggplot2)
library(ggrepel)

ggplot(midwest, aes(state, area)) +
  geom_violin() +
  geom_sina() +
  geom_label_repel(box.padding = 0.5, min.segment.length = 0.5, aes(label = county), data=midwest %>% subset(poptotal>1000000), size=3)

enter image description here

You can see how the line from the label always goes to the midline, but not the point (see WAYNE and OAKLAND county in MI).

jsirgo
  • 156
  • 8
  • So sorry. I have edited. – jsirgo Oct 08 '21 at 16:31
  • I don't think there's a simple way to do this, but there are some hacky methods which essentially create the plot, extract the dot positions, and then feed those into a revised version of the plot. See here for some examples using a different ggplot2 geom: https://stackoverflow.com/questions/9789871/method-to-extract-stat-smooth-line-fit – Jon Spring Oct 08 '21 at 19:02

1 Answers1

2

I haven't seen a satisfying answer to this kind of question yet. The general approach I've seen has been to create the plot using the mapping transformation, then to extract the transformed values, and then use those to plot the layer using those transformed values.

EDIT: Added set.seed before each round of plotting

library(tidyverse)
set.seed(0)
a <- ggplot(midwest, aes(state, area)) +
  geom_violin() +
  geom_sina()
  
a_guts <- ggplot_build(a)$data[[2]] %>% 
  bind_cols(midwest %>% 
              mutate(state_num = as.integer(as.factor(state))) %>%
              select(state_num, area, county, poptotal)) %>% 
  subset(poptotal>1E6)


set.seed(0)
a + geom_point(data = a_guts, aes(x = x, y = y), 
               size = 3, color = "red", shape = 22, fill = NA) +
  geom_label_repel(data = a_guts,
                   aes(x = x, y = y, label = county), color = "red",
                   box.padding = 2, min.segment.length = 0.5, size=3)

enter image description here

Jon Spring
  • 55,165
  • 4
  • 35
  • 53