извлечение подмножества данных на основе того, содержит ли транзакция хотя бы часть временного диапазона в R - PullRequest
1 голос
/ 29 апреля 2020

У меня есть фрейм данных df , который содержит различные транзакции. Каждая транзакция имеет дату начала и дату окончания. Две переменные для этого: start_time и end_time . Они относятся к классу POSIXct . Пример того, как они выглядят: «2018-05-23 23:40:00» «2018-06-24 00:10:00». В df содержится около 13000 транзакций, и я хочу извлечь все транзакции, которые содержат хотя бы бит указанного временного интервала, если не все. Временной интервал или диапазон составляет 20:00:00 - 8:00:00, поэтому в основном 8 вечера = <интервал <8:00 </p>

Я пытаюсь использовать dplyr и функцию filter() чтобы сделать это, однако моя проблема в том, что я не уверен, как написать логическое выражение. Пока что я написал в коде следующее:

df %>% filter(hour(start_time) >= 20 | hour(start_time) < 8 |hour(end_time) >= 20 | hour(end_time) < 8 )

Я думал, может быть, это получит все транзакции, которые содержат хотя бы часть этого интервала, но потом я подумал о транзакциях, которые может начинаться и заканчиваться за пределами этого интервала, но их продолжительность настолько велика, что содержит эти часы из интервала. Я подумал, может быть, добавить | duration > 12, потому что любое время запуска, которое длится более 12 часов, будет содержать часть этого временного интервала. Тем не менее, я чувствую, что этот код неоправданно длинен и должен быть более простой способ, но я не знаю как.

1 Ответ

0 голосов
/ 29 апреля 2020

Я начну с примера фрейма данных, поскольку в вопросе не указан образец df:

library(lubridate)
library(dplyr)

set.seed(69)
dates <- as.POSIXct("2020-04-01") + days(sample(30, 10, TRUE))
start_time <- dates + seconds(sample(86400, 10, TRUE))
end_time  <- start_time + seconds(sample(50000, 10, TRUE))
df <- data.frame(Transaction = LETTERS[1:10], start_time, end_time)

df
#>    Transaction          start_time            end_time
#> 1            A 2020-04-18 16:51:03 2020-04-19 00:05:54
#> 2            B 2020-04-28 21:32:10 2020-04-29 06:18:06
#> 3            C 2020-04-03 02:12:52 2020-04-03 06:11:20
#> 4            D 2020-04-17 19:15:43 2020-04-17 21:01:52
#> 5            E 2020-04-09 11:36:19 2020-04-09 19:01:14
#> 6            F 2020-04-14 20:51:25 2020-04-15 06:08:10
#> 7            G 2020-04-08 12:01:55 2020-04-09 01:45:53
#> 8            H 2020-04-16 01:43:38 2020-04-16 04:22:39
#> 9            I 2020-04-08 23:11:51 2020-04-09 09:04:26
#> 10           J 2020-04-07 12:28:08 2020-04-07 12:55:42

Мы можем перечислить возможности для совпадения следующим образом:

  1. Любое время запуска до 08:00 или после 20: 00
  2. Любое время остановки до 08:00 или после 20: 00
  3. Время остановки и запуска различаются даты.

Используя небольшую модульную математику, мы можем записать это как:

df %>% filter((hour(start_time) + 12) %% 20 > 11 | 
              (hour(end_time) + 12) %% 20 > 11 | 
              date(start_time) != date(end_time))
#>   Transaction          start_time            end_time
#> 1           A 2020-04-18 16:51:03 2020-04-19 00:05:54
#> 2           B 2020-04-28 21:32:10 2020-04-29 06:18:06
#> 3           C 2020-04-03 02:12:52 2020-04-03 06:11:20
#> 4           D 2020-04-17 19:15:43 2020-04-17 21:01:52
#> 5           F 2020-04-14 20:51:25 2020-04-15 06:08:10
#> 6           G 2020-04-08 12:01:55 2020-04-09 01:45:53
#> 7           H 2020-04-16 01:43:38 2020-04-16 04:22:39
#> 8           I 2020-04-08 23:11:51 2020-04-09 09:04:26

Вы можете проверить, что все времена хотя бы частично находятся в заданном диапазоне, и что две удаленные строки не являются.

...