Как включить метки для сегментированной geom_smooth в r?

#r #ggplot2 #dplyr #tidyverse

Вопрос:

Я хотел бы пометить свой geom_smooth в r, но метки расположены ближе к фактическим точкам, а не к линиям.

Данные:

 df lt;- structure(list(t = c(45, 45, 45, 45, 45, 46, 46, 46, 46, 46,  47, 47, 47, 47, 47, 48, 48, 48, 48, 48, 49, 49, 49, 49, 49, 50,  50, 50, 50, 50, 51, 51, 51, 51, 51, 52, 52, 52, 52, 52, 53, 53,  53, 53, 53, 54, 54, 54, 54, 54, 55, 55, 55, 55, 55, 56, 56, 56,  56, 56, 57, 57, 57, 57, 57, 58, 58, 58, 58, 58, 59, 59, 59, 59,  59, 60, 60, 60, 60, 60, 61, 61, 61, 61, 61, 62, 62, 62, 62, 62,  63, 63, 63, 63, 63, 64, 64, 64, 64, 64, 65, 65, 65, 65, 65),   x = c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), name = c("P1", "P2",   "P2 ", "P3", "P4", "P1", "P2", "P2 ", "P3", "P4", "P1", "P2",   "P2 ", "P3", "P4", "P1", "P2", "P2 ", "P3", "P4", "P1", "P2",   "P2 ", "P3", "P4", "P1", "P2", "P2 ", "P3", "P4", "P1", "P2",   "P2 ", "P3", "P4", "P1", "P2", "P2 ", "P3", "P4", "P1", "P2",   "P2 ", "P3", "P4", "P1", "P2", "P2 ", "P3", "P4", "P1", "P2",   "P2 ", "P3", "P4", "P1", "P2", "P2 ", "P3", "P4", "P1", "P2",   "P2 ", "P3", "P4", "P1", "P2", "P2 ", "P3", "P4", "P1", "P2",   "P2 ", "P3", "P4", "P1", "P2", "P2 ", "P3", "P4", "P1", "P2",   "P2 ", "P3", "P4", "P1", "P2", "P2 ", "P3", "P4", "P1", "P2",   "P2 ", "P3", "P4", "P1", "P2", "P2 ", "P3", "P4", "P1", "P2",   "P2 ", "P3", "P4"), value = c(48L, 132L, 111L, 115L, 2L,   58L, 126L, 82L, 74L, 0L, 45L, 119L, 78L, 87L, 0L, 56L, 106L,   105L, 88L, 1L, 52L, 78L, 91L, 107L, 1L, 35L, 96L, 86L, 98L,   1L, 61L, 118L, 90L, 108L, 2L, 45L, 114L, 93L, 98L, 2L, 55L,   108L, 78L, 76L, 7L, 44L, 97L, 94L, 96L, 0L, 40L, 111L, 93L,   88L, 1L, 43L, 78L, 66L, 113L, 2L, 20L, 57L, 84L, 41L, 0L,   17L, 51L, 81L, 34L, 0L, 40L, 55L, 64L, 32L, 0L, 25L, 67L,   71L, 37L, 0L, 16L, 67L, 60L, 57L, 0L, 23L, 46L, 62L, 47L,   1L, 34L, 75L, 68L, 39L, 0L, 34L, 60L, 85L, 24L, 0L, 20L,   58L, 63L, 37L, 1L)), row.names = c(NA, -105L), class = c("tbl_df",  "tbl", "data.frame"))  

Мой код:

 df %gt;%   group_by(name) %gt;%   # New column to label the first and last values  mutate(label =  case_when(  t == min(t) | t == max(t) ~ name,  TRUE ~ NA_character_)) %gt;%   ggplot(aes(x = t, y = value, color = name, group = interaction(x, name), shape = name))    geom_smooth(se = F)    geom_vline(xintercept = 57, linetype = "dashed", lwd = 0.3)     scale_color_discrete(guide = 'none')    geom_label_repel(aes(label = label))  

Мой график: введите описание изображения здесь

Кроме того, можно ли избавиться от линий, указывающих на сглаженные лессовые кривые?

Комментарии:

1. вы пробовали просто использовать ggplot2::geom_label ?

2. Небольшие линии, указывающие на сглаженные лессовые кривые, сделаны ggrepel. Чтобы удалить их, либо используйте geom_label , как предложено выше, либо geom_label_repel(..., min.segment.length = 1) в этом случае они печатаются только тогда, когда этикетка находится слишком далеко от кривой из-за отталкивания. Другой вариант-это ..., segment.colour=NA, ...

Ответ №1:

Одним из вариантов достижения желаемого результата было бы использование stat="smooth" в ggrepel::geom_label_repel . Это приведет к размещению меток на установленных точках, а не на точках данных. Однако, чтобы это сработало, вам нужно добавить метки на лету внутри geom_label_repel , например, с помощью after_stat(ifelse(x %in% range(x), color, NA_character_)) :

 library(ggplot2) library(ggrepel)  ggplot(df, aes(x = t, y = value, color = name, group = interaction(x, name), shape = name))    geom_smooth(se = F)    geom_vline(xintercept = 57, linetype = "dashed", lwd = 0.3)    scale_color_discrete(guide = "none")    ggrepel::geom_label_repel(aes(label = after_stat(ifelse(x %in% range(x), color, NA_character_))), stat = "smooth")  

РЕДАКТИРОВАТЬ Вероятно, существуют разные маршруты для размещения меток слева (справа) в (нижнем) верхнем конце диапазона данных. Мой подход, вероятно, не элегантен. Но после того, как в последнее время мне пришлось подготовить множество диаграмм с надписями на конечных точках, я решил, что сделать это с помощью двух текстовых слоев, на мой взгляд, самый простой способ добиться этого, поскольку он позволяет нам нажимать, чтобы сдвинуть надписи влево или вправо. Чтобы сделать эту работу, я увеличил масштаб x, чтобы освободить место для надписей. Кроме того, я удалил сегменты в правке и установил .direction = "y" так что метки отталкиваются только в направлении y.

 library(ggplot2) library(ggrepel)  ggplot(df, aes(x = t, y = value, color = name, group = interaction(x, name), shape = name))    geom_smooth(se = F)    geom_vline(xintercept = 57, linetype = "dashed", lwd = 0.3)    scale_color_discrete(guide = "none")    scale_x_continuous(expand = c(.1, .1))    ggrepel::geom_label_repel(aes(label = after_stat(ifelse(x %in% range(x)[1], color, NA_character_))),   stat = "smooth",  nudge_x = -1,  min.segment.length = Inf,  direction = "y")    ggrepel::geom_label_repel(aes(label = after_stat(ifelse(x %in% range(x)[2], color, NA_character_))),   stat = "smooth",  nudge_x = 1,  min.segment.length = Inf,  direction = "y")  

Комментарии:

1. Спасибо за этот замечательный ответ. Еще одна вещь, вы знаете, как я могу разместить метки за пределами xranges? например, те, что справа, должны быть при x = 65 и далее, а те, что слева, должны быть меньше x = 45?