简体   繁体   English

使用 ggplot2 将持续时间绘制为线条

[英]Plot durations as lines with ggplot2

Last days, I've pondering the following problem:I want to plot the duration of an activity as a line, with the y axis representing the date the activity happens and the x axis representing time in hours.最近几天,我在思考以下问题:我想将活动的持续时间绘制为一条线,y 轴代表活动发生的日期,x 轴代表以小时为单位的时间。 When I deal with an activity that starts and ends in the same day this is easy.当我处理在同一天开始和结束的活动时,这很容易。

For example:例如:

df1<-structure(list(Date = structure(c(16802, 16803, 16805, 16806, 
16809, 16810, 16812, 16813, 16816, 16820, 16821, 16822, 16829
), class = "Date"), hms1 = structure(c(1457623680, 1457620860, 
1457621160, 1457622540, 1457625600, 1457621280, 1457620380, 1457619720, 
1457623620, 1457621460, 1457620440, 1457617980, 1457621880), class =      c("POSIXct", "POSIXt"), tzone = ""), hms2 = structure(c(1457632500, 1457627640, 
1457628360, 1457629500, 1457631000, 1457625120, 1457625420, 1457624520, 
1457627640, 1457626800, 1457626800, 1457622060, 1457625540), class = c("POSIXct", 
"POSIXt"), tzone = "")), .Names = c("Date", "hms1", "hms2"), class =     "data.frame", row.names = c(103L, 105L, 108L, 110L, 114L, 117L, 120L, 122L, 127L, 135L, 136L, 138L, 145L))

p1<-ggplot(df1, aes(x=Date,y= hms1))+ scale_x_date(breaks = date_breaks("1 day"))+
geom_linerange(aes(ymin = hms1, ymax = hms2),color = "red",size = 2)+ coord_flip()
p1+ylab("Time")+ggtitle("Activity During Day")

gives desired plot:给出所需的情节: ggplot1

Note that the real date, is on column Date while the dates in hms1m hms2 is wrong due to the process that I used to get the time in H:M:S format.请注意,实际日期在 Date 列中,而 hms1m hms2 中的日期是错误的,因为我过去使用 H:M:S 格式获取时间的过程。

df1$hms1 <- format(df1$time, format = "%H:%M:%S")
df1$hms1 <- as.POSIXct(df1$hms1, format = "%H:%M:%S")

Thing is that most of the "activities", I'm trying to plot span in two day periods.事情是大多数“活动”,我试图在两天内绘制跨度。 The only solution I have come up with up to now, is shifting both the datetime values by an appropriate period, in order to "artificialy" place them in the same day, as suggested here 2 .到目前为止,我提出的唯一解决方案是将两个日期时间值移动一个适当的时间段,以便“人为地”将它们放在同一天,如此处建议的2 This process though, naturally results in the x axis displaying the "artificial" timestamps.不过,这个过程自然会导致 x 轴显示“人工”时间戳。

How could I take control of the tick marks in ggplot, so I can make them display the right timestamps?我如何控制 ggplot 中的刻度线,以便让它们显示正确的时间戳? Or even better can someone propose a more elegant solution?或者甚至更好,有人可以提出更优雅的解决方案吗? To be clear: I want the y-axis to be just the date of the start of the event, but the x-axis to span more than 24 hours.明确地说:我希望 y 轴只是事件开始的日期,但 x 轴跨越 24 小时以上。

I'm not sure what your real data structure looks like, so I created some time periods for illustration as follows: I used your values for Date and then used runif to select some random start and end times for each activity.我不确定您的真实数据结构是什么样的,所以我创建了一些时间段来进行说明,如下所示:我使用了Date的值,然后使用runif为每个活动选择了一些随机的开始和结束时间。 Some time periods occur within a single date and some span two dates.有些时间段发生在一个日期内,有些则跨越两个日期。

I then plotted the data as follows: Plot horizontal lines that are located vertically at the date when the activity began.然后我按如下方式绘制数据:绘制活动开始日期垂直的水平线。 The line begins at the time (in hours) when the activity started (relative to Midnight on the date when the activity started), and then extends to the right for however many hours the activity lasted.这条线从活动开始的时间(以小时为单位)开始(相对于活动开始日期的午夜),然后向右延伸活动持续了多少小时。

The horizontal scale extends to 48 hours, so that activities covering more than one date can be visualized.水平刻度扩展到 48 小时,以便可以可视化涵盖多个日期的活动。 Vertical lines mark date boundaries, so you can see which activities continued into a second day.垂直线标记日期边界,因此您可以查看哪些活动持续到第二天。 If you have activities lasting three or more days, just extend the horizontal scale as needed to accommodate them.如果您的活动持续三天或更长时间,只需根据需要扩展水平比例以适应它们。

# Convert Date to POSIXct and set HMS to beginning of day (i.e., Midnight).
# To do this, I added 8-hours to account for my locale being the U.S. Pacific time zone.
df1$Date = as.POSIXct(df1$Date) + 3600*8

## Create some times for start and end of each activity
set.seed(20)
df1$hms1a = df1$Date  + runif(nrow(df1), 3600*5, 3600*10)
df1$hms2a = df1$Date + runif(nrow(df1), 3600*15, 3600*40)

library(ggplot2)
library(scales)
library(stringr)

ggplot(df1, aes(x=Date)) + 
  scale_x_datetime(breaks = date_breaks("1 day")) +
  scale_y_continuous(limits = c(0,48), breaks=seq(0,48,2), 
                     labels=str_pad(seq(0,48,2) %% 24, 2, pad="0")) +
  geom_hline(yintercept=seq(0,48,24)) +
  geom_linerange(aes(ymin = hms1a - Date, ymax = hms2a - Date), color = "red",size = 2) + 
  coord_flip() + ylab("Time (hours)") + 
  ggtitle("Activity During Day")

在此处输入图片说明

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM