0

I would like to reproduce the following plot, but I would like to add date labels every 4 months instead of numeric.

enter image description here

I had to convert the date_time values to numeric in order to plot the annotate("rect") as I wanted it to extend the length of the rectangle to the edge of the plot, similar to geom_hline. I found the annotate approach the quickest. I now have an issue, as I would like to have date labels on the x axis instead of numeric.

I have tried using scale_x_continuous but this took too long and doesn't seem to work.

Thanks for your help.

# Reproducible data
set.seed(123)

start_date_time <- as.POSIXct("2023-07-01 00:00:00")
end_date_time <- as.POSIXct("2023-07-02 00:00:00")
date_time <- seq(from = start_date_time, to = end_date_time, by = "15 min")

depth <- runif(length(date_time), min = 0, max = 0.5)

df <- data.frame(date_time = date_time, depth = depth)

df$N_dt <- as.numeric(df$date_time)
x_point <- min(df$N_dt)

full_level <- 0.4
pipe_bottom <- 0.15
pipe_top <- 0.35
pipe <- 0.25

df %>%
  ggplot(aes(x = N_dt,
             y = depth)) +
  geom_line(size = 0.25) +
  labs(x = "Date", 
       y = "Water level (m)") +
  geom_hline(yintercept = full_level, linetype = 'dashed', 
             color = 'black') +
  annotate("text", x = x_point, y = (full_level + 0.03),
           label = "Full level", size = 8 / .pt) +
  annotate("text", x = x_point, y = pipe,
           label = "Pipe", size = 8 / .pt) +
  annotate("rect", xmin = -Inf, xmax = Inf,
           ymin = pipe_bottom, ymax = pipe_top, alpha = .1) +
  theme_classic() +
  theme(
    plot.title = element_blank(),
    axis.text = element_text(size = 8),
    axis.title = element_text(size = 8.5),
    legend.title = element_blank(),
    legend.position = "top",
    panel.border = element_rect(color = "black", fill = NA)
  )
mrob27
  • 61
  • 6

2 Answers2

2

You can use the labels argument of scale_x_continuous to convert the numbers back to date-times.

df %>%
  ggplot(aes(x = N_dt,
             y = depth)) +
  geom_line(size = 0.25) +
  labs(y = "Water level (m)") +
  scale_x_continuous(labels = ~ format(as.POSIXct(.x, origin = '1970-01-01'),
                                       '%d %b %Y %H:%M')) +
  geom_hline(yintercept = full_level, linetype = 'dashed', 
             color = 'black') +
  annotate("text", x = x_point, y = (full_level + 0.03),
           label = "Full level", size = 8 / .pt) +
  annotate("text", x = x_point, y = pipe,
           label = "Pipe", size = 8 / .pt) +
  annotate("rect", xmin = -Inf, xmax = Inf,
           ymin = pipe_bottom, ymax = pipe_top, alpha = .1) +
  theme_classic() +
  theme(
    plot.title = element_blank(),
    axis.text = element_text(size = 8),
    axis.title = element_text(size = 8.5),
    legend.title = element_blank(),
    legend.position = "top",
    panel.border = element_rect(color = "black", fill = NA)
  )

enter image description here

Allan Cameron
  • 147,086
  • 7
  • 49
  • 87
2

One option would be to stick with the date times which will allow you set your desired date breaks easily via scale_x_datetime. To make this work with your rect I set the xmin and xmax directly according to the range of your dates. Tricky part at this step is that doing so we have to account for the expansion:

library(ggplot2)

# Set the range for the rects
range_rect <- range(df$date_time)
# Add some expansion
range_rect <- range_rect + .1 * c(-1, 1) * diff(range_rect)

x_point <- min(df$date_time)

df %>%
  ggplot(aes(
    x = date_time,
    y = depth
  )) +
  geom_line(size = 0.25) +
  labs(
    x = "Date",
    y = "Water level (m)"
  ) +
  geom_hline(
    yintercept = full_level, linetype = "dashed",
    color = "black"
  ) +
  annotate("text",
    x = x_point, y = (full_level + 0.03),
    label = "Full level", size = 8 / .pt
  ) +
  annotate("text",
    x = x_point, y = pipe,
    label = "Pipe", size = 8 / .pt
  ) +
  annotate("rect",
    xmin = range_rect[[1]], xmax = range_rect[[2]],
    ymin = pipe_bottom, ymax = pipe_top, alpha = .1
  ) +
  # As we already added the expansion via range_rect,
  # set it to zero for the scale
  scale_x_datetime(
    expand = c(0, 0)
  ) +
  theme_classic() +
  theme(
    plot.title = element_blank(),
    axis.text = element_text(size = 8),
    axis.title = element_text(size = 8.5),
    legend.title = element_blank(),
    legend.position = "top",
    panel.border = element_rect(color = "black", fill = NA)
  )

enter image description here

stefan
  • 90,330
  • 6
  • 25
  • 51