ggplot2:将非连续持续时间绘制为条形图

时间:2013-06-15 06:07:12

标签: r ggplot2

我正在使用ggplot将各种事件绘制为它们开始的日期(x轴)和开始时间(y轴)的函数。数据/代码如下:

date<-c("2013-06-05","2013-06-05","2013-06-04","2013-06-04","2013-06-04","2013-06-04","2013-06-04",
    "2013-06-04","2013-06-04","2013-06-03","2013-06-03","2013-06-03","2013-06-03","2013-06-03",
    "2013-06-02","2013-06-02","2013-06-02","2013-06-02","2013-06-02","2013-06-02","2013-06-02")
start <-c("07:36:00","01:30:00","22:19:00","22:12:00","20:16:00","19:19:00","09:00:00",
     "06:45:00","01:03:00","22:15:00","19:05:00","08:59:00","08:01:00","07:08:00",
     "23:24:00","20:39:00","18:53:00","16:57:00","15:07:00","14:33:00","13:24:00")
duration <-c(0.5,6.1,2.18,0.12,1.93,0.95,10.32,
         2.25,5.7,2.78,3.17,9.03,0.95,0.88,
         7.73,2.75,1.77,1.92,1.83,0.57,1.13)
event <-c("AF201","SS431","BE201","CD331","HG511","CD331","WQ115",
      "CD331","SS431","WQ115","HG511","WQ115","CD331","AF201",
      "SS431","WQ115","HG511","WQ115","CD331","AS335","CD331")

df<-data.frame(date,start,duration,event)

library(ggplot2)
library(scales)

p <- ggplot(df, aes(as.Date(date),as.POSIXct(start,format='%H:%M:%S'),color=event))
p <- p+geom_point(alpha = I(6/10),size=5) 
p + ylab("time (hr)") + xlab("date") + scale_x_date(labels = date_format("%m/%d")) +
scale_y_datetime(labels = date_format("%H"))+
scale_colour_hue(h=c(360, 90))
theme(axis.text.x = element_text(hjust=1, angle=0))  

结果情节如下所示:

enter image description here

问题:我不是简单地用单点指示事件的开始时间(如上所示),而是如何绘制跨越事件持续时间的条形图?如上面的数据框所示,我有这个持续时间数据(以小时为单位)。或者,我可以提供“停止时间”(未显示)。

我想象解决方案看起来像堆积条形图。但是,条形图不是很正确,因为它假设条形图从图的底部开始,并且垂直堆叠的事件在它们之间没有间隙。我的事件可能是非连续的 - 沿着y轴在不同位置“开始”和“停止”。解决方案还必须考虑到:1)某些事件可能最终并发(时间重叠)和2)某些事件将跨越多天。

我非常感谢任何建议!

4 个答案:

答案 0 :(得分:4)

有点不清楚你想要什么 - @ Michele的回答似乎很好,我不清楚你是否想要使用geom_rect因为它会产生更粗的线条(如果是这样,只需更改线宽),或者如果还有其他原因。我决定使用geom_rect来试一试,以便躲避。我用x轴上的起始日期和y上的开始和结束时间绘制了它。我设置的数据略有不同以启用它。如果您追求的是不同的东西,请尽量明确,但至少这是另一种选择:

df<-data.frame(date,start,duration,event)

df <- transform(df,
                start = as.POSIXct(paste(date, start)),
                end   = as.POSIXct(paste(date, start)) + duration*3600)

df <- df[c("event", "start", "end")]

df$date <- strptime(df$start, "%Y-%m-%d")
df$start.new <- format(df$start, format = "%H:%M:%S")
df$end.new <- format(df$end, format = "%H:%M:%S")
df$day <- factor(as.POSIXct(df$date))
levels(df$day) <- 1:4
df$day <- as.numeric(as.character(df$day))
df$event.int <- df$event
levels(df$event.int) <- 1:7
df$event.int <- as.numeric(as.character(df$event.int))

p <- ggplot(df, aes(day, start)) + geom_rect(aes(ymin = start, ymax = end,
                                            xmin = (day - 0.45) + event.int/10,
                                            xmax = (day - 0.35) + event.int/10,
                                            fill = event)) +
  scale_x_discrete(limits = 1:4,breaks = 1:4, labels = sort(unique(date)),
                   name = "Start date") + ylab("Duration")

enter image description here

答案 1 :(得分:3)

感谢(+ 1s)@Michele和​​@alexwhan的输入。使用geom_rect我能够获得x轴上同一点上同一日期发生的所有事件。 (我预计这个数据集可能最终会包含数月的事件。)

df<-data.frame(date,start,duration,event)

library(ggplot2)

p <- ggplot(df, aes(xmin=as.Date(date),xmax=as.Date(date)+1,
                    ymin=as.POSIXct(start,format='%H:%M:%S'),
                    ymax=as.POSIXct(start,format='%H:%M:%S')+duration*3600,
                    fill=event))
p <- p+geom_rect(alpha = I(8/10)) 
p + ylab("time") + xlab("date") + scale_x_date(labels = date_format("%m/%d")) +
scale_y_datetime(labels = date_format("%H"))+
scale_colour_hue(h=c(360, 90))
theme(axis.text.x = element_text(hjust=1, angle=0))   

...导致这个: enter image description here

这与我的目标非常接近。 我想我可以通过调整alpha来处理潜在的过度绘图问题。 理想情况下,我希望y轴只包含一天(00到00)。要做到这一点,我想我可能需要重新格式化数据,以便持续时间超过午夜的事件被重新分配到第二天。 (不知道如何在R中执行此操作。)

答案 2 :(得分:2)

尝试这种方法。可能它与您的计划有所不同,但我认为这是一种非常清晰的方式来显示您的数据:

df<-data.frame(date,start,duration,event)

df <- transform(df,
                start = as.POSIXct(paste(date, start)),
                end   = as.POSIXct(paste(date, start)) + duration*3600)

df <- df[c("event", "start", "end")]

library(reshape2)

df <- melt(df, id.vars="event")
df$value <- as.POSIXct(df$value, origin=as.Date("1970-01-01"))

df <- df[order(df$event, df$value),]

df$eventID <- rep(seq(1, nrow(df)/2, 1), each=2)

library(ggplot2)

ggplot(df) +
  geom_line(aes(value, event, group=eventID, color=event))

enter image description here

答案 3 :(得分:0)

结合以下优点:(i)y轴包含单个~24小时的时间段; (ii)不重叠的事件; (iii)除图例外,图中标注的事件; (iv)简明的代码。

node_modules

情节图片:

Image of plot