ggrepel: использование position_dodge в сочетании с geom_label_repel

Я пытаюсь пометить выбросы в geom_boxplot с помощью ggrepel::geom_label_repel. Это хорошо работает, когда есть только одна группирующая переменная, но когда я пробую это для нескольких группирующих переменных, я сталкиваюсь с проблемой. По какой-то причине аргумент position в ggrepel работает не очень последовательно, см. этот пример:

library(tidyverse)
library(ggrepel)

set.seed(1337)

df <- tibble(x = rnorm(500),
             g1 = factor(sample(c('A','B'), 500, replace = TRUE)),
             g2 = factor(sample(c('A','B'), 500, replace = TRUE)),
             rownames = 1:500)

is_outlier <- function(x) {
    return(x < quantile(x, 0.25) - 1.5 * IQR(x) | x > quantile(x, 0.75) + 1.5 * IQR(x))
}

df_outliers <- df %>% group_by(g1, g2) %>% mutate(outlier=is_outlier(x))

ggplot(df_outliers, aes(x=g1, y=x, fill=g2)) + 
    geom_boxplot(width=0.3, position = position_dodge(0.5)) +
    ggrepel::geom_label_repel(data=. %>% filter(outlier), 
                              aes(label=rownames), position = position_dodge(0.8))

Результирующий график

Есть ли способ сделать так, чтобы метки указывали на сопутствующие точки с помощью ggrepel?


person Ravi    schedule 19.11.2018    source источник
comment
Я думаю, что по крайней мере часть проблемы связана с отсутствием выбросов B (g1) A (g2). Вы можете получить уклонение, добавив эту комбинацию в . %>% filter(outlier) %>% group_by(g1) %>% complete(g2). Однако это не решает проблему рисования линий с помощью ggrepel.   -  person aosmith    schedule 20.11.2018


Ответы (1)


Вы можете попробовать это:

ggplot(df_outliers, 
       aes(x=g1, y=x, fill=g2, label=rownames)) + 
  geom_boxplot(width = 0.3, position = position_dodge(0.5)) +
  geom_label_repel(data = . %>%
                     filter(outlier) %>%
                     group_by(g1) %>%
                     complete(g2, fill = list(x = 0, rownames = "")),
                   position = position_dodge(0.5),
                   box.padding = 1,
                   min.segment.length = 0,
                   show.legend = FALSE)

результат

Пояснения:

  1. Источник данных для geom_label_repel() следует предложению aosmith добавить комбинацию B-A, заполнив 0 для x (подойдет любое число, если это не NA по умолчанию) и "" для имени строки (ggrepel не будет отображать пустые метки, но будет учитывать их при уклонении).

  2. box.padding устанавливается на 1 (увеличено по сравнению с 0,25 по умолчанию), чтобы отодвигать метки дальше, чтобы сегменты линий были более заметными.

  3. min.segment.length устанавливается на 0 (уменьшено по сравнению с 0,5 по умолчанию), чтобы принудительно отображать линейные сегменты, независимо от того, насколько они короткие.

(show.legend = FALSE не является обязательным. Мне просто не нравится, когда в легенде появляется буква «а».)

person Z.Lin    schedule 16.01.2019