在 R 中确定 date/time 间隔是否跨越中午,而不管这一天
determine if a date/time interval spans noon, regardless of the day, in R
我有一个 df
描述了一只鸟在夏天造访它的巢穴的次数。这包括每次访问的开始时间和结束时间 (POSIXct)。
df <- read.csv(text="
starttime,endtime,duration
2015-03-23 11:07:10,2015-03-23 17:57:10,420
2015-03-31 22:47:10,2015-04-01 06:47:10,490
2015-04-11 23:47:10,2015-04-12 06:17:10,400
2015-04-14 00:07:10,2015-04-15 06:27:10,1830
2015-06-23 02:17:10,2015-06-25 04:07:10,3000", stringsAsFactors=FALSE)
df$starttime <- as.POSIXct(df$starttime)
df$endtime <- as.POSIXct(df$endtime)
我需要确定的是每次访问是否跨越中午时间 (12:00),而不考虑访问日期。在多日访问的情况下,我还需要确定中午时间过去的次数。
我不知道从哪里开始。想法?
format(df$starttime, format = "%p") == "AM" & format(df$endtime, format="%p") == "PM"
# [1] TRUE FALSE FALSE FALSE FALSE
这可能对区域设置敏感,因此您可能需要更加小心。
AM <- format(as.POSIXct("2020-01-01 06:00:00"), format = "%p")
format(df$starttime, format = "%p") == AM & format(df$endtime, format="%p") != AM
# [1] TRUE FALSE FALSE FALSE FALSE
要获得中午的数量,我们可以将该技术与“天”的计数相结合:
round(difftime(df$endtime, df$starttime, units="days"), 0)
# Time differences in days
# [1] 0 0 0 1 2
获得
pmax(+(format(df$starttime, format = "%p") == AM & format(df$endtime, format="%p") != AM),
round(difftime(df$endtime, df$starttime, units="days"), 0))
# [1] 1 0 0 1 2
在 dplyr
的帮助下,这里有一个可以计算中午次数的函数
count_noons <- function(start, end) {
stopifnot(all(start<end))
full_days <- pmax(0, date(end) - date(start) - 1)
full_days + (lubridate::hour(start) <=12) + (lubridate::hour(end) >=12) - (date(start)==date(end))
}
with(df, count_noons(starttime, endtime))
基本思路是看第一天和最后一天是否过了中午(但如果开始和结束在同一天就不要重复计算)然后加上天数差在开始和结束之间(因为每一天都有一个中午)
我测试了几个案例
df <- read.csv(text="
starttime,endtime
2015-03-23 11:07:10,2015-03-23 17:57:10
2015-03-31 22:47:10,2015-04-01 06:47:10
2015-04-11 23:47:10,2015-04-12 06:17:10
2015-04-12 13:47:10,2015-04-12 19:17:10
2015-04-14 00:07:10,2015-04-15 06:27:10
2015-06-23 02:17:10,2015-06-25 04:07:10
2015-06-23 02:17:10,2015-06-25 14:07:10", stringsAsFactors=FALSE)
df$starttime <- as.POSIXct(df$starttime)
df$endtime <- as.POSIXct(df$endtime)
然后我得到
transform(df, noons=count_noons(starttime, endtime))
# starttime endtime noons
# 1 2015-03-23 11:07:10 2015-03-23 17:57:10 1
# 2 2015-03-31 22:47:10 2015-04-01 06:47:10 0
# 3 2015-04-11 23:47:10 2015-04-12 06:17:10 0
# 4 2015-04-12 13:47:10 2015-04-12 19:17:10 0
# 5 2015-04-14 00:07:10 2015-04-15 06:27:10 1
# 6 2015-06-23 02:17:10 2015-06-25 04:07:10 2
# 7 2015-06-23 02:17:10 2015-06-25 14:07:10 3
我有一个 df
描述了一只鸟在夏天造访它的巢穴的次数。这包括每次访问的开始时间和结束时间 (POSIXct)。
df <- read.csv(text="
starttime,endtime,duration
2015-03-23 11:07:10,2015-03-23 17:57:10,420
2015-03-31 22:47:10,2015-04-01 06:47:10,490
2015-04-11 23:47:10,2015-04-12 06:17:10,400
2015-04-14 00:07:10,2015-04-15 06:27:10,1830
2015-06-23 02:17:10,2015-06-25 04:07:10,3000", stringsAsFactors=FALSE)
df$starttime <- as.POSIXct(df$starttime)
df$endtime <- as.POSIXct(df$endtime)
我需要确定的是每次访问是否跨越中午时间 (12:00),而不考虑访问日期。在多日访问的情况下,我还需要确定中午时间过去的次数。
我不知道从哪里开始。想法?
format(df$starttime, format = "%p") == "AM" & format(df$endtime, format="%p") == "PM"
# [1] TRUE FALSE FALSE FALSE FALSE
这可能对区域设置敏感,因此您可能需要更加小心。
AM <- format(as.POSIXct("2020-01-01 06:00:00"), format = "%p")
format(df$starttime, format = "%p") == AM & format(df$endtime, format="%p") != AM
# [1] TRUE FALSE FALSE FALSE FALSE
要获得中午的数量,我们可以将该技术与“天”的计数相结合:
round(difftime(df$endtime, df$starttime, units="days"), 0)
# Time differences in days
# [1] 0 0 0 1 2
获得
pmax(+(format(df$starttime, format = "%p") == AM & format(df$endtime, format="%p") != AM),
round(difftime(df$endtime, df$starttime, units="days"), 0))
# [1] 1 0 0 1 2
在 dplyr
count_noons <- function(start, end) {
stopifnot(all(start<end))
full_days <- pmax(0, date(end) - date(start) - 1)
full_days + (lubridate::hour(start) <=12) + (lubridate::hour(end) >=12) - (date(start)==date(end))
}
with(df, count_noons(starttime, endtime))
基本思路是看第一天和最后一天是否过了中午(但如果开始和结束在同一天就不要重复计算)然后加上天数差在开始和结束之间(因为每一天都有一个中午)
我测试了几个案例
df <- read.csv(text="
starttime,endtime
2015-03-23 11:07:10,2015-03-23 17:57:10
2015-03-31 22:47:10,2015-04-01 06:47:10
2015-04-11 23:47:10,2015-04-12 06:17:10
2015-04-12 13:47:10,2015-04-12 19:17:10
2015-04-14 00:07:10,2015-04-15 06:27:10
2015-06-23 02:17:10,2015-06-25 04:07:10
2015-06-23 02:17:10,2015-06-25 14:07:10", stringsAsFactors=FALSE)
df$starttime <- as.POSIXct(df$starttime)
df$endtime <- as.POSIXct(df$endtime)
然后我得到
transform(df, noons=count_noons(starttime, endtime))
# starttime endtime noons
# 1 2015-03-23 11:07:10 2015-03-23 17:57:10 1
# 2 2015-03-31 22:47:10 2015-04-01 06:47:10 0
# 3 2015-04-11 23:47:10 2015-04-12 06:17:10 0
# 4 2015-04-12 13:47:10 2015-04-12 19:17:10 0
# 5 2015-04-14 00:07:10 2015-04-15 06:27:10 1
# 6 2015-06-23 02:17:10 2015-06-25 04:07:10 2
# 7 2015-06-23 02:17:10 2015-06-25 14:07:10 3