R不知道时间是循环的吗?如何找到一天中最接近给定时间的时间

Does R not know that time is circular? How to find closest time of the day to a given time

例如,

23:59:59 点比 03:00:00 点更接近午夜。不幸的是,R 告诉相反(至少我使用的包)。这就是我的意思:

事实上,我不仅关心午夜,而且我需要在向量中找到一天中最接近给定时间的时间,我不关心日期。有一个很好的 answer 的类似问题,但代码没有按预期工作,因为在 link 中,时间是一个时间轴而不是一个圆圈。看这里:

library("chron")
x <- times(c("00:00:02", "23:59:59"))
v <- times("00:00:00")
indx <- which(abs(x-v) == min(abs(x - v)))
x[indx]
00:00:02 # which is further from 00:00:00 than 23:59:59

根据代码,00:00:00 和 23:59:59 之间的所有时间都比 23:59:59 更接近午夜。例如,这会导致令人困惑的结果,即 16:23:11 比 23:59:59 更接近午夜。所以 R 似乎从 00:00:00 开始并在 23:59:59 结束,因此 "does not see" 23:59:59 非常接近 00:00:00。我知道如果我们考虑日期,这是有道理的:例如,2001-01-01 00:00:02 比 2001-01-01 23:59:59 更接近 2001-01-01 00:00:00 ] 到 2001-01-01 00:00:00。但是如何找到一天中最接近时间的时间?

编辑以获得更通用的解决方案:

如果您正在为这个问题寻找一个不错的通用解决方案:

由于上述解决方案仅适用于非常具体的情况,因此我尝试创建一个更通用的解决方案。我创建了一个函数,它将在最接近给定时间的向量中找到时间。

library('chron')

#' This function returns the time in 'timeVector' that is 
#' closest to 'time'
closest.time <- function(timeVector, time) {
  times()
  x <- times(timeVector)
  v <- times(time)

  clockwise_distance = abs(x - v) 
  anticlockwise_distance = times("23:59:59") - clockwise_distance + times("00:00:01")
  clockwise_and_anticlockwise <-  matrix(c(anticlockwise_distance,  clockwise_distance), ncol = 2)
  shortest_distance_of_the_two <- apply(clockwise_and_anticlockwise, 1, min)

  indx <- which(shortest_distance_of_the_two == min(shortest_distance_of_the_two))

  x[indx]
}

这个解决方案基于这样一种想法,即有两种方法可以绕过这个圆圈。第一个只是正常的顺时针距离。第二个是逆时针距离。由于整圈是24小时,所以逆时针方向的距离是'24_hours - clockwise_distance'。

然后对于 timesVector 中的每个值,应该检查顺时针或逆时针距离是否最短。

最后,应该检查 timeVector 中的哪个时间最接近 time

旧答案

由于 chron 没有很好的功能来执行此操作,而且我无法提出使用 times 数据类型的解决方案,因此我将放弃 times 并改用 POSIXct。

POSIXct 还有一个您说过不想使用的日期属性。这就是为什么我们的 POSIXct 中的日期只是一个虚拟值,我们并不真正关注它,除非以解决我们问题的方式改变它。

x <- c("00:00:02", "23:59:59")
x <- as.POSIXct(x, format = "%H:%M:%OS")
v <- as.POSIXct("00:00:00", format = "%H:%M:%OS")

# I subtract 24 hours to center all times around the same midnight.
mid.day <- as.POSIXct("12:00:00", format = "%H:%M:%OS")
x[x > mid.day] <- x[x > mid.day] - 24*60*60

# I used your same approach to check the time closest to midnight.
# you might want to change this to something that uses difftime(). Ask me if you  need help with this.
indx <- which(abs(x-v) == min(abs(x - v)))

# shows us the POSIXct object the way we want to see it (only time)
format(x[indx], format="%H:%M:%S")

请注意,您现在可能想使用 difftime(x,y) 来获取时差

 indx <- which(abs(difftime(x, v)) == min(abs(difftime(x, v))))