最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

r - ggplot2 x-axis with many hours for each of many days. Is there a way to span the dates in the x-axis over the hours for that

programmeradmin0浏览0评论

I have a dataset which runs over many days. For each day, I have multiple hours. In this toy example, I am looking for 3 days and, for each of the three days, I am looking at the data for 13 individual hours (from 6am to 6pm).

I want to capture both the date and the hour in the x-axis. However, rather than repeat the date for each of the 13 individuals hours, I'd like to span the date across those hours, something like tab_spanner in gt.

For example, consider this sample code:

library(ggplot2)

exp<-data.frame(
  date = c(rep("2025-02-01", 13), rep("2025-02-02", 13),rep("2025-02-03", 13)),
  hour = rep(seq(6, 18, 1),3),
  obs = runif(13*3, min=1, max=50)
)

exp |>
  mutate(
    date.hour = factor(paste0(date, " ", hour, " hour"), levels=unique(paste0(date, " ", hour, " hour")), ordered=TRUE) 
  ) |>
  ggplot(aes(x=date.hour, y=obs, group=1)) +
  geom_line() + 
  theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1))

This will generate the following graph:

However, what I am wondering is if it is possible to span the date across the hours, to create a graph that looks something like this:

I have a dataset which runs over many days. For each day, I have multiple hours. In this toy example, I am looking for 3 days and, for each of the three days, I am looking at the data for 13 individual hours (from 6am to 6pm).

I want to capture both the date and the hour in the x-axis. However, rather than repeat the date for each of the 13 individuals hours, I'd like to span the date across those hours, something like tab_spanner in gt.

For example, consider this sample code:

library(ggplot2)

exp<-data.frame(
  date = c(rep("2025-02-01", 13), rep("2025-02-02", 13),rep("2025-02-03", 13)),
  hour = rep(seq(6, 18, 1),3),
  obs = runif(13*3, min=1, max=50)
)

exp |>
  mutate(
    date.hour = factor(paste0(date, " ", hour, " hour"), levels=unique(paste0(date, " ", hour, " hour")), ordered=TRUE) 
  ) |>
  ggplot(aes(x=date.hour, y=obs, group=1)) +
  geom_line() + 
  theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1))

This will generate the following graph:

However, what I am wondering is if it is possible to span the date across the hours, to create a graph that looks something like this:

Share Improve this question asked Feb 3 at 19:51 JBurnsJBurns 1357 bronze badges 1
  • Map hour to the x axis and facet_wrap(vars(date), nrow = 1). You can play with options in facet_wrap() and theme() to move the facet labels to the bottom, remove spaces between facets, etc. – zephryl Commented Feb 3 at 20:13
Add a comment  | 

1 Answer 1

Reset to default 1

Using the recently released legendry package you can achieve your desired result easily using guide_axis_nested like so, i.e. map the interaction of date and hour on x, set the delimiter to split the variables using key_range_auto and set the style for each level of axis labels using levels_text= which expects a list of element_text elements.

library(ggplot2)
library(legendry)

exp |>
  ggplot(
    aes(
      x = interaction(hour, date),
      y = obs, group = 1
    )
  ) +
  geom_line() +
  guides(x = guide_axis_nested(
    key = key_range_auto(sep = "\\."),
    levels_text = list(
      element_text(angle = 90, vjust = 0.5, hjust = 1),
      element_text(angle = 0, hjust = .5)
    )
  ))

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论