ggrepel изменить сегменты

Пытаюсь добавить метки к своим точкам с точкой джиттера. Я определил положение с помощью pos и использовал geom_label с pos вместо отключения джиттера. Это работает хорошо, но смысл этого заключался в том, чтобы добавить метки к некоторым из моих точек. Я использую geom_text_repel (также пробовал с geom_label_repel), но не могу получить соответствующую маркировку. Как вы можете видеть на моем рисунке, сегменты ведут себя странно, особенно для PDAC104. Какой вариант, чтобы отрезок от метки был до точки (именно до точки, а не в миллиметрах, как здесь). Я пробовал разные варианты заполнения, но мне не удалось заставить все работать.

Спасибо,

M

my.label <- stat_ind_pi1_ok %>% filter(Pop1=="Is" | ID=="PDAC64")
pos <- position_jitter(width = 0.2, seed=1)
Plot_pi1_indPop <- stat_ind_pi1_ok %>% filter(Pop1=="bla" | Pop1=="ME" | Pop1=="Nafr" | Pop1=="Is") %>%
  ggplot(aes(x = Pop1, y = mean_pi_pc, colour = Pop1)) +
    geom_point(position = pos, alpha=0.35, size=2) +
    geom_text_repel(data=my.label, mapping=aes(label=ID), position=pos, label.size = NA, fill = NA, size=3,
                     max.overlaps = Inf, min.segment.length=0, box.padding=0.5, label.padding=0, point.padding=0) +
    stat_summary(fun = mean, geom = "point", size = 5) +
    coord_flip() +
    scale_color_hue() +
    labs(x = NULL, y = "Pi (%)") +
    theme_light() +
    theme(
      legend.position = "none",
      axis.title = element_text(size = 12),
      axis.text.x = element_text(size = 10),
      panel.grid = element_blank()
    ) ; Plot_pi1_indPop

Мой сюжетЯ


person user236152    schedule 09.06.2020    source источник
comment
Я думаю, это объяснение может быть тем, что вам нужно.   -  person Gregor Thomas    schedule 09.06.2020
comment
К вашему сведению, лучший способ написать Pop1=="bla" | Pop1=="ME" | Pop1=="Nafr" | Pop1=="Is" - это Pop1 %in% c("bla", "ME", "Nafr", "Is")   -  person Gregor Thomas    schedule 09.06.2020


Ответы (1)


Это довольно интересно - спасибо за ваш вопрос. Здесь виноваты не ваш код и подход к вашему графику, а способ, которым position_jitter() применяется к набору данных. Объект, созданный из position_jitter(), в основном можно рассматривать как массив значений джиттера, который применяется к вашему набору данных построчно. Имейте в виду, я не точно уверен, что это действительно то, что происходит, но поведение соответствует такому способу работы.

Определение проблемы

Итак, что здесь происходит? Что ж, сначала позвольте мне создать фиктивный набор данных для использования в качестве примера.

set.seed(1234)
df <- data.frame(x=1:10, y=rnorm(10))

Я построю набор данных и применю предварительно созданный объект position_jitter() к geom_point() и geom_text_repel(). Вы увидите, что на выходном графике все сегменты совпадают с точками, как и следовало ожидать.

pos <- position_jitter(width=0.5, seed=1)
ggplot(df, aes(x,y)) + geom_point(position=pos) +
  geom_text_repel(aes(label=x), color='red', position=pos, force=20)

введите здесь описание изображения

Проблемы становятся очевидными, если мы применяем geom_point() ко всему набору данных, но применяем geom_text_repel() к подмножеству этого набора данных (что в основном является вашим собственным случаем).

df_rep <- df %>% dplyr::filter(x > 5)

ggplot(df, aes(x,y)) + geom_point(position=pos) +
  geom_text_repel(data=df_rep, aes(label=x), color='red', position=pos, force=20)

введите здесь описание изображения

Теперь сегменты не выстраиваются в линию, что вы и наблюдаете. Ключевым моментом здесь является понимание того, что pos вообще не связано с наборами данных, используемыми для построения графиков. Если вы думаете об этом как о числовом векторе, который умножается на эстетику x перед построением графика, поведение имеет смысл. Первое наблюдение в полном наборе данных корректируется на то же значение, что и первый набор в подмножестве, но это означает, что определенные наблюдения не колеблются одинаково, если только они не находятся в одной и той же последовательности в обоих наборах данных.< /em> Мы можем проверить гипотезу о том, как работает pos, создав набор данных, состоящий из первых нескольких строк из df и последних нескольких строк из df. Если наша гипотеза верна, то первые несколько строк должны быть в порядке, но дрожание для последних нескольких строк будет другим. Давайте проверим это:

df_rep2 <- df[c(1:3, 8:10),]   # choosing first few and last few obs in df
ggplot(df, aes(x,y)) + geom_point(position=pos) +
  geom_text_repel(data=df_rep2, aes(label=x), color='red', position=pos, force=20)

введите здесь описание изображения

Теперь должно быть совершенно очевидно, почему линии расположены не так, как точки в вашем примере.

Как решить проблему

Так что исправить? Итак, мы знаем, что pos нужно применять в той же последовательности к объектам geom_point() и geom_text_repel(). Я бы хотел, чтобы был более элегантный способ сделать это (и, возможно, он есть), но вы можете избежать этого, используя два отдельных вызова geom_point(): один соответствует набору данных, используемому для geom_text_repel(), а другой — «всему остальному».

По крайней мере, есть хороший способ определить «все остальное» — использовать anti_join() из dplyr. Вот исправление:

df_not <- anti_join(df, df_rep)  # find everything in df that is not df_rep
ggplot(df, aes(x,y)) +
  geom_point(data=df_not, position=pos) +
  geom_point(data=df_rep, position=pos) +
  geom_text_repel(data=df[which(df$x>5),], aes(label=x), color='red', position=pos, force=20)

введите здесь описание изображения

person chemdork123    schedule 09.06.2020