rggplot2timeserieschart

X-axis scale over night


I have data collected over night with timestamps. I would like to plot this so that the x-axis runs from 9pm to 5am, but I can't figure out how to do it.

Here is some dummy data:

    library(tidyverse)
    library(hms)
     
test <- data.frame(day = as.factor(rep(1:3, each = 8)),
               time = rep(seq(from = as.POSIXct("2025-05-03 21:00", tz = "UTC"), 
                              to = as.POSIXct("2025-05-04 04:00", tz = "UTC"), 
                              by = "hour"), 3),
               count = sample(1:50, 24, replace = TRUE)) %>%
  mutate(time = as_hms(time))

test %>%
  ggplot(aes(x = time, y = count, fill = day)) +
  geom_bar(position = "dodge", stat = "identity")

What I know to make:

simple bar plot running from 00:00 to 24:00

A bad paint version of what I want:

simple bar plot running from 8pm to 4am


Solution

  • Recognizing that your use of geom_bar is just a placeholder for real data and other plot needs, I think your main concern is how to adjust time and the x-axis so that it does just what you want. For that, we can adjust time so that before "noon" is extended to be past "midnight". One side-effect of this is that scale_x_time() happily shows the times as (say) 28:00, so we need to adjust the labels as well.

    test |>
      mutate(time = hms::as_hms(time + if_else(time < as_hms("12:00:00"), 86400, 0))) |>
      ggplot(aes(x = time, y = count, fill = day)) +
      geom_bar(position = "dodge", stat = "identity") +
      scale_x_time(labels = ~ as_hms(as.numeric(.x) %% 86400))
    

    ggplot2 grob that shows over-night and fixes the x-axis

    If you prefer midnight to be 24:00:00 instead of 00:00:00, adjust the scale

    ... +
      scale_x_time(labels = ~ hms::as_hms((as.numeric(.x) - 1) %% 86400 + 1))