Как соединить geom_point() с geom_line при использовании Faceting()?

У меня есть проблема, и я ничего не нашел в Интернете по этому поводу. Буду рад получить некоторые подсказки.

У меня есть набор данных, в котором ось x дискретна, но я хотел бы соединить точки друг с другом (что я могу сделать). Моя проблема заключается в том, что я добавляю параметр огранки. Я больше не могу связывать точки друг с другом. Я нашел альтернативу, НО она выглядит не очень.

Это простой воспроизводимый пример:

# Create a simple dataset
dat <- data.frame(Days = c(rep("Monday", 6), rep("Tuesday", 6), rep("Wednesday", 6)),
                  Shift = rep(c("Morning", "Evening", "Night"), 6),
                  Group = c(rep("Group1", 3), rep("Group2", 3), rep("Group1", 3), rep("Group2", 3), rep("Group1", 3), rep("Group2", 3)),
                  Amount = c(6, 5, 6, 2, 3, 1, 5, 4, 6, 1, 2, 2, 5, 4, 7, 3, 1, 2)) 
# Change into factor to have the order I need
dat$Days <- factor(dat$Days, levels = c("Monday", "Tuesday", "Wednesday"))
dat$Shift <- factor(dat$Shift, levels = c("Morning", "Evening", "Night"))

# The plot I am stuck with
# The last dot of Monday night should be linked to Tuesday morning
ggplot(data = dat, aes(x = Shift, y = Amount)) + geom_point() +
    geom_line(aes(group = Group)) + facet_grid(.~Days) +
    theme(panel.spacing = unit(0, "lines"))

# This is the alternative I found, but clearly not great
ggplot(data = dat, aes(x = interaction(Days, Shift, sep = "\n", lex.order = T), y = Amount)) + geom_point(aes(color = Group)) +
    geom_line(aes(group = Group)) +
    geom_vline(xintercept = c(3, 6, 9),
               color = "darkred", linetype = 2)

а здесь почти дубликат stackoverflow.com/questions/66553823/…

tjebo 05.04.2023 18:04

Из этой ветки мудрый комментарий пользователя @gregorthomas: «Фасеты — это отдельные графы. Похоже, фасеты вам не нужны...»

tjebo 05.04.2023 18:05

@tjebo спасибо за публикацию этих тем! я их не нашел! Да, я согласен, что фасеты для отдельных графиков, но в моем случае я хотел разбить их по дням недели... Вот и запутался, как этого добиться.

Robin.N. 06.04.2023 07:24

Теперь я понимаю, что вы в основном ищете вложенные метки осей? Другой подход: stackoverflow.com/questions/20571306/… или stackoverflow.com/questions/44616530/…

tjebo 08.04.2023 13:29

@tjebo ВАУ! Это потрясающе! Это более простой вариант и чистый! Я не знал термина "вложенные метки осей"... Таким образом, это лучше всего решает мою проблему! Спасибо!

Robin.N. 11.04.2023 08:54
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
6
55
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Я не думаю, что есть простой способ связать данные между фасетами, используя стандартный синтаксис ggplot2. Я видел подходы, которые впоследствии увеличивают его, проникая во внутренности, например. используя ggplot_build или пакет grid.

Ваш второй подход «подделки граней» кажется мне более простым. Это может выглядеть чище с большей настройкой. Например:

ggplot(data = dat, aes(x = interaction(Days, Shift, sep = "\n", lex.order = T),
                       y = Amount)) + 
  geom_point(aes(color = Group)) +
  geom_vline(xintercept = c(3, 6, 9),
             color = "darkred", linetype = 2) +
  annotate("rect", xmin = c(0.5,3.5,6.5), xmax = c(3.5,6.5,9.5),
           ymin = 6.4, ymax = 7, fill = "gray80", color = "gray90") +
  annotate("text", x = c(2,5,8), y = 7, vjust = 1.5, 
           label = c("Monday", "Tuesday","Wednesday")) +
  geom_vline(xintercept = c(0.5,3.5,6.5), color = "white", size = 2) +
  geom_line(aes(group = Group)) +

  scale_x_discrete(labels = dat$Shift, name = "Shift") +
  coord_cartesian(ylim = c(0.5, 7), expand = FALSE) 

Недостатком моего конкретного подхода здесь является то, что прямоугольники меток фасетов должны иметь размер в зависимости от вашего выходного разрешения, т. Е. Если вы изменяете размер вывода, вы можете, например, настроить ymin аннотации "rect".

После обзора я думаю, что это считается довольно близким обманом ответа здесь. Я не приму на свой счет, если люди проголосуют за закрытие. :-) stackoverflow.com/questions/66553823/…

Jon Spring 05.04.2023 18:37

Спасибо! Извините, @Jon Spring, я не нашел тему, которую вы опубликовали... Я буду работать с обоими!

Robin.N. 06.04.2023 07:22

Другой вариант — использовать patchwork для создания трех отдельных графиков, но установить ограничения с помощью coord_cartesian, чтобы на график отображался только один день. К сожалению, я не нашел способа установить ограничения напрямую через coord_cartesian, как это можно сделать через limits аргумент шкалы, т.е. мы должны передать числовой диапазон. Как следствие, нам потребуется некоторая ручная работа, чтобы вручную вычислить числовые пределы.

library(ggplot2)
library(patchwork)

plot_fun <- function(limits) {
  day <- unique(limits$Days)
  breaks = as.character(limits$x)
  limits <- as.numeric(unique(dat$x))[levels(dat$x) %in% limits$x]
  
  theme_adjust <- if (!day %in% c("Monday")) {
    theme(axis.text.y = element_blank(),
          axis.title.y = element_blank(),
          axis.line.y = element_blank(),
          axis.ticks.length.y = unit(0, "pt")
        )
  }
  
  labs <- if (!day == "Tuesday") labs(x = NULL) else labs(x = "Shift")
  
  ggplot(data = dat, aes(x = x, y = Amount)) +
    geom_point() +
    geom_line(aes(group = Group)) +
    facet_wrap(~as.character(day)) +
    scale_x_discrete(breaks = breaks, labels = ~ gsub("^(.*)\\..*$", "\\1", .x), expand = c(0, .5)) +
    coord_cartesian(xlim = range(limits)) +
    theme_adjust +
    theme(plot.margin = margin()) +
    labs
}

dat$x <- interaction(dat$Shift, dat$Days)

xlims <- dat[!duplicated(dat$x), c("Days", "x")]
xlims <- split(xlims, xlims$Days)

p <- lapply(xlims, plot_fun) 

p |> 
  wrap_plots() &
  theme(panel.spacing.x = unit(0, "pt"))

Спасибо! Я никогда не использовал пакет пэчворк, но он выглядит довольно интересно! Буду копать глубже :)

Robin.N. 06.04.2023 07:23

Другие вопросы по теме