В моем последнем посте я показал несколько примеров использования пакета lubridate от R, и еще одной проблемой, которую было действительно легко решить, было выяснение того, насколько близко определенное время было к выходным.
Я хотел написать функцию, которая возвращала бы предыдущее воскресенье или предстоящую субботу, в зависимости от того, что было ближе.
Функции lubridate floor_date и terrace_date делают это довольно просто.
Например, если мы хотим округлить 18 декабря до начала недели и до начала следующей недели, мы можем сделать следующее:
1
2
3
4
5
6
|
> library(lubridate) > floor_date(ymd( "2014-12-18" ), "week" ) [ 1 ] "2014-12-14 UTC" > ceiling_date(ymd( "2014-12-18" ), "week" ) [ 1 ] "2014-12-21 UTC" |
Для даты в будущем мы на самом деле хотим взять субботу, а не воскресенье, поэтому мы вычтем один день из этого:
1
2
|
> ceiling_date(ymd( "2014-12-18" ), "week" ) - days( 1 ) [ 1 ] "2014-12-20 UTC" |
Теперь давайте соберем это вместе в функцию, которая находит ближайшие выходные для данной даты:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
findClosestWeekendDay = function(dateToLookup) { before = floor_date(dateToLookup, "week" ) + hours( 23 ) + minutes( 59 ) + seconds( 59 ) after = ceiling_date(dateToLookup, "week" ) - days( 1 ) if ((dateToLookup - before) < (after - dateToLookup)) { before } else { after } } > findClosestWeekendDay(ymd_hms( "2014-12-13 13:33:29" )) [ 1 ] "2014-12-13 UTC" > findClosestWeekendDay(ymd_hms( "2014-12-14 18:33:29" )) [ 1 ] "2014-12-14 23:59:59 UTC" > findClosestWeekendDay(ymd_hms( "2014-12-15 18:33:29" )) [ 1 ] "2014-12-14 23:59:59 UTC" > findClosestWeekendDay(ymd_hms( "2014-12-17 11:33:29" )) [ 1 ] "2014-12-14 23:59:59 UTC" > findClosestWeekendDay(ymd_hms( "2014-12-17 13:33:29" )) [ 1 ] "2014-12-20 UTC" > findClosestWeekendDay(ymd_hms( "2014-12-19 13:33:29" )) [ 1 ] "2014-12-20 UTC" |
Я установил воскресную дату в 23:59:59, чтобы я мог использовать эту дату на следующем шаге, где мы хотим вычислить, сколько часов это от текущей даты до ближайших выходных.
Я закончил с этой функцией:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
distanceFromWeekend = function(dateToLookup) { before = floor_date(dateToLookup, "week" ) + hours( 23 ) + minutes( 59 ) + seconds( 59 ) after = ceiling_date(dateToLookup, "week" ) - days( 1 ) timeToBefore = dateToLookup - before timeToAfter = after - dateToLookup if (timeToBefore < 0 || timeToAfter < 0 ) { 0 } else { if (timeToBefore < timeToAfter) { timeToBefore / dhours( 1 ) } else { timeToAfter / dhours( 1 ) } } } > distanceFromWeekend(ymd_hms( "2014-12-13 13:33:29" )) [ 1 ] 0 > distanceFromWeekend(ymd_hms( "2014-12-14 18:33:29" )) [ 1 ] 0 > distanceFromWeekend(ymd_hms( "2014-12-15 18:33:29" )) [ 1 ] 18.55833 > distanceFromWeekend(ymd_hms( "2014-12-17 11:33:29" )) [ 1 ] 59.55833 > distanceFromWeekend(ymd_hms( "2014-12-17 13:33:29" )) [ 1 ] 58.44194 > distanceFromWeekend(ymd_hms( "2014-12-19 13:33:29" )) [ 1 ] 10.44194 |
Хотя это работает довольно медленно, когда вы запускаете его во фрейме данных, который содержит много строк.
Должен быть умный R способ сделать то же самое (возможно, с использованием матриц), который я еще не понял, так что, если вы знаете, как ускорить это, дайте мне знать.
Ссылка: | R: Время в / из выходных от нашего партнера JCG Марка Нидхэма в блоге Марка Нидхэма |