r - plot arrival and departure times that cross midnight
问题描述
I am trying to plot an animal's arrival to and departure from a given site. The animal arrives in the afternoon/evening and departs the following morning. Sometimes the animal arrives after midnight, thus both arrival and departure occur on the same date.
How can I scale the x axis so that the times are centered around midnight? In both examples in the reprex below, the problem is that the x axis is scaled from morning to night, thus showing the animal's departure time from the previous day before its arrival time that night, whereas what I would like is to show each day's arrival time and what time it departed the next day. How can I scale the x axis so each segment begins at the arrival time and ends at the departure time the following morning?
Thank you for any ideas!
library(lubridate)
#>
#> Attaching package: 'lubridate'
#> The following objects are masked from 'package:base':
#>
#> date, intersect, setdiff, union
library(hms)
#>
#> Attaching package: 'hms'
#> The following object is masked from 'package:lubridate':
#>
#> hms
library(tidyverse)
library(ggplot2)
library(reprex)
df <- data.frame(
date = as.Date(c("2021-04-19", "2021-04-20", "2021-04-21", "2021-04-22", "2021-04-23", "2021-04-24", "2021-04-26")),
arrival_time = ymd_hms(c("2021-04-19 19:03:00", "2021-04-20 19:50:00", "2021-04-21 20:04:00", "2021-04-22 20:52:00", "2021-04-23 21:06:00",
"2021-04-24 21:22:00", "2021-04-26 01:47:00")),
departure_time = ymd_hms(c("2021-04-20 06:00:00", "2021-04-21 05:47:00", "2021-04-22 06:23:00", "2021-04-23 05:56:00",
"2021-04-24 04:59:00", "2021-04-25 06:32:00", "2021-04-27 06:40:00"))
)
# attempt 1 - plot separate date variable on y axis
ggplot(df) +
geom_segment(aes(x = as_hms(arrival_time), xend = as_hms(departure_time), y = date, yend = date)) +
scale_y_date(date_breaks = "1 day", date_labels = "%d %b") +
labs(x = "Time at Site",
y = "Date")
# attempt 2 - plot actual date of POSIXct variable on y axis
ggplot(df) +
geom_segment(aes(x = as_hms(arrival_time), xend = as_hms(departure_time), y = date(arrival_time), yend = date(departure_time))) +
scale_y_date(date_breaks = "1 day", date_labels = "%d %b") +
labs(x = "Time at Site",
y = "Date")
Created on 2021-07-29 by the reprex package (v1.0.0)
解决方案
You could try subtracting 12 hours from the times then adding 12 hours to their labels.
First write a labelling function:
# The hms format stores time as seconds internally.
# There are 86400 seconds in 24 hours and 43200 seconds in 12 hours, so our
# labelling function adds 43200 seconds to increase the time values by 12
# hours, then gives the result modulo 86400 to deal with values above 24 hours.
# The result is an integer number of seconds, so we need to convert this with as_hms.
# Finally we take the first 5 characters of the result with substr to give %H:%M
# formatted character strings as the labels
labelling_fn <- function(x) {
(as.numeric(x + 43200) %% 86400) %>%
as_hms() %>%
substr(1, 5)
}
Now pass the labelling function to the labels
argument of scale_x_time
df %>%
ggplot(aes(y = date(arrival_time), xmin = as_hms(arrival_time - hours(12)),
xmax = as_hms(departure_time - hours(12)))) +
geom_linerange() +
scale_x_time(labels = labelling_fn) +
scale_y_date(date_breaks = "1 day", date_labels = "%d %b") +
labs(x = "Time at Site",
y = "Date")
推荐阅读
- javascript - 在 Vuetify 中垂直对齐多个 v-slide-group
- javascript - 谁能解释一下这段代码的输出?
- c# - URL has been blocked by CORS policy
- http - 是否有必要为 Web 应用程序中的所有页面包含 Cache-Control 标头?
- c++ - 带有 Rcpp 的 R 包
- google-chrome - 使用 Chrome 激活 Gmail 消息或打开新的 Gmail 消息窗口
- javascript - 获取 Vuejs 中 seo 友好 url 的 url 参数
- vb.net - 使用()和不使用()声明数据表类有什么区别
- java - java中与延迟接口关联的getDelay(TimeUnit)
- python-3.x - 无法列出 Azure 容器中的 Blob