Как добавить затенение в ночное время с geom_rect без расширения масштабов фасетов? - PullRequest
2 голосов
/ 29 октября 2019

У меня есть кадр данных со значением, измеренным прибором в четырех местах в течение последовательных периодов времени. Я хочу, чтобы ночная пора (с 6 вечера до 6 утра) была затенена серым, чтобы помочь с интерпретацией. Код ниже показывает это правильно, за исключением того, что я также хочу использовать facet_grid(..., scales = 'free_x'), чтобы отбросить нежелательные периоды времени, когда прибор не собирал данные в каждом месте.

require(ggplot2)

df.long <- data.frame(Timestamp = seq.POSIXt(as.POSIXct("2018-07-05 18:00:00", format = '%Y-%m-%d %H:%M:%S'), by = 'hour', length.out = 192),
                      Location = c(rep('A', 48), rep('B', 48), rep('C', 48), rep('D', 48)),
                      value = sin(seq(1:192)/4))

shade <- data.frame(dusk = seq.POSIXt(as.POSIXct("2018-07-05 18:00:00", format = '%Y-%m-%d %H:%M:%S'), by = 'day', length.out = 8), 
                    dawn = seq.POSIXt(as.POSIXct("2018-07-06 06:00:00", format = '%Y-%m-%d %H:%M:%S'), by = 'day', length.out = 8),
                    top = Inf,
                    bottom = -Inf)

ggplot(df.long) +
  geom_rect(data = shade, 
            aes(xmin = dusk, xmax = dawn,ymin = bottom, ymax = top), 
            fill = 'light grey', alpha = 0.5) +
  geom_line(aes(x = Timestamp, y = value, col = Location)) +
  geom_point(aes(x = Timestamp, y = value, fill = Location), pch = 21) +
  facet_grid( ~ Location, scales = 'free_x') +
  ylab('Flux (mg O2 m-2 h-1)') +
  theme_bw()

enter image description here

Ось X правильно масштабируется с помощью facet_grid(..., scales = 'free_x'), когда я исключаю вызов для geom_rect. Как мне построить черную geom_rect на втором графике без увеличения шкалы по оси X?

ggplot(df.long) +
  # geom_rect(data = shade, aes(xmin = dusk, xmax = dawn,
  #                             ymin = bottom, ymax = top), fill = 'light grey', alpha = 0.5) +
  geom_line(aes(x = Timestamp, y = value, col = Location)) +
  geom_point(aes(x = Timestamp, y = value, fill = Location), pch = 21) +
  facet_grid( ~ Location, scales = 'free_x') +
  ylab('Flux (mg O2 m-2 h-1)') +
  theme_bw() +
  theme(legend.position = 'none')

enter image description here

У меня также естьпопытался заменить geom_rect на:

annotate("rect", 
         xmin = shade$dusk, xmax = shade$dawn, ymin = shade$bottom, ymax = shade$top, 
         fill = "light grey", alpha = 0.5) +

1 Ответ

1 голос
/ 29 октября 2019

Один из возможных подходов - определить только соответствующие прямоугольники штриховки для каждого фасета:

library(dplyr)

shade2 <- shade %>%
  # replicate shade for each facet
  slice(rep(seq(1, n()),
            times = n_distinct(df.long$Location))) %>%
  mutate(Location = rep(sort(unique(df.long$Location)),
                        each = n()/4)) %>%

  # calculate actual x-range associated with each facet, & join with shade
  left_join(df.long %>%
              group_by(Location) %>%
              summarise(xmin = min(Timestamp),
                        xmax = max(Timestamp)) %>%
              ungroup(),
            by = "Location") %>%

  # for each shade facet, keep only rows within relevant x-range
  filter(dusk >= xmin & dawn <= xmax)

ggplot(df.long) +
  geom_rect(data = shade2, # replace shade with shade2, everything else is unchanged
            aes(xmin = dusk, xmax = dawn,
                ymin = bottom, ymax = top),
            fill = 'light grey', alpha = 0.5) +
  geom_line(aes(x = Timestamp, y = value, col = Location)) +
  geom_point(aes(x = Timestamp, y = value, fill = Location), pch = 21) +
  facet_grid( ~ Location, scales = 'free_x') +
  ylab('Flux (mg O2 m-2 h-1)') +
  theme_bw()

plot

...