首页 > 解决方案 > 创建有间隙的时间线

问题描述

假设我们有一个超过 2 年的时间表。每年,我们都想在特定的日子做一些事情,并在时间轴上标记这些日子。类似于 Gant char,但不同之处在于句点之间可以有间隔。这意味着例如从 13. 到 20. 4 月有一个活动,下一个活动从 1. 到 8. 同年 5 月。在下面的 MWE 中,为简单起见,我仅使用从 2000 年 1 月 1 日到 2000 年 2 月 28 日的时间段:

library(data.table)
library(ggplot2)
x <- seq(as.Date("2000/01/01"),
         as.Date("2000/02/28"), "day")
y <- x
y[c(3,6,8,9,34:43,50:59)] <- NA
x[c(1,2,3,12:33,44:58)] <- NA
timetable <- data.table(Year=c(rep("Year_1",59),rep("Year_2",59)),
date=c(x,y))

如何创建以矩形形式说明活动的时间表?与此处显示的图表类似: 带有 R 的甘特图 或此处: 在 R 中使用 ggplot2 创建多项目时间线 但此处应该允许两者之间存在间隙。

所以换句话说,我要做的是填写现有的时间表,并省略没有活动的日子(空白)。如何做到这一点ggplot2

标签: rggplot2datatable

解决方案


所以这是一种可能性;您首先找出哪些日期是缺失值,然后运行长度对缺失进行编码:

is_missing <- timetable[, rle(is.na(date)), by = Year]

由此,您可以轻松计算表格中未丢失日期的位置:

end <- cumsum(is_missing$lengths)
start <- end - is_missing$lengths + 1

# Take now only the parts that are not missing
end <- end[!is_missing$values]
start <- start[!is_missing$values]

由此,您可以构建一个包含期间开始和结束日期的新数据框:

newdf <- data.frame(
  Year  = timetable$Year[start],
  start = timetable$date[start],
  end   = timetable$date[end]
)
newdf$y <- 1:nrow(newdf) # just a counter for visualisation

您可以使用它来绘制如下内容:

ggplot(newdf) +
  geom_rect(aes(xmin = start, xmax = end, 
                ymin = 0 + y,
                ymax = 1 + y, fill = Year))

在此处输入图像描述

请注意,该Year变量并不真正意味着年份,因为日期本身仅跨越一年(2000 年),因此我将其视为分类变量。此外,第 3 和第 6 个条目newdf只有一天,在图中显示为零宽度矩形,因为它在同一点开始和结束:

> newdf
    Year      start        end y
1 Year_1 2000-01-04 2000-01-11 1
2 Year_1 2000-02-03 2000-02-12 2
3 Year_1 2000-02-28 2000-02-28 3
4 Year_2 2000-01-01 2000-01-02 4
5 Year_2 2000-01-04 2000-01-05 5
6 Year_2 2000-01-07 2000-01-07 6
7 Year_2 2000-01-10 2000-02-02 7
8 Year_2 2000-02-13 2000-02-18 8

如果您希望这些 1 天的时间段出现,您可以在函数内部执行xmax = end + 1或操作。xmin = start - 1aes()

编辑:对于Yeary 轴上的变量,您可以将它们视为数字geom_rect()

ggplot(newdf) +
  geom_rect(aes(xmin = start, xmax = end, 
                ymin = -0.45 + as.numeric(Year),
                ymax = 0.45 + as.numeric(Year), fill = Year)) +
  scale_y_continuous(breaks = seq_len(nlevels(newdf$Year)),
                     labels = levels(newdf$Year))

在此处输入图像描述


推荐阅读