Разве R не знает, что время круговое? Как найти ближайшее время дня к данному времени - PullRequest
1 голос
/ 27 мая 2019

23: 59: 59, например, ближе к полуночи, чем 03:00:00 к полуночи.К сожалению, R говорит об обратном (по крайней мере, пакет, который я использую).Вот что я имею в виду:

image

На самом деле меня волнует не только полночь, но мне нужно найти ближайшее векторное время в векторев данное время, и я не забочусь о дате.Есть похожий вопрос с отличным ответом , но код работает не так, как ожидалось, потому что во время ссылки временная шкала не является кругом.Смотрите здесь:

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 и, таким образом, «не видит», что 23:59:59 довольно близко к 00:00:00.Я понимаю, что это имеет смысл, если принять во внимание даты: например, 2001-01-01 00:00:02 ближе к 2001-01-01 00:00:00, чем 2001-01-01 23:59:С 59 по 2001-01-01 00:00:00.Но как найти ближайшее время дня, когда человек считает время кругом?

1 Ответ

1 голос
/ 27 мая 2019

Отредактируйте для более общего решения:

Если вы просто ищете хорошее общее решение для этой проблемы:

Так как это решение выше применимо только для очень конкретной ситуации, я попробовалсоздать более общее решение.Я создал функцию, которая найдет время в векторе, ближайшем к данному времени.

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, я собираюсь отказаться от времен и использовать вместо этого 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))))
...