创建有差距的时间表

时间:2019-10-16 21:04:42

标签: r ggplot2 datatable

假设我们有两年的时间表。每年,我们都希望在某些日子做某事,并在时间表上标记这些日子。与Gant char类似,但不同之处在于句点之间可能会有间隔。例如,这意味着在同一年的4月13日至20日有活动,在下一个活动是1月1日至8日。在下面的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))

如何创建时间表以矩形形式说明活动?与此处显示的图表相似: Gantt charts with R 或在这里: Creating a Multi-Project Timeline Using ggplot2 in R 但是这里应该在两者之间留出空隙。

换句话说,我想做的是填写现有的时间轴,而将没有活动的日子留在原处(空白)。如何使用ggplot2完成此操作?

1 个答案:

答案 0 :(得分:0)

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

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))

enter image description here

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

> 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()

编辑:对于y轴上的Year变量,您可以在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))

enter image description here