Как фильтровать по нескольким временным диапазонам в R? - PullRequest
1 голос
/ 08 мая 2020

У меня есть фрейм данных со столбцом DateTime и некоторыми другими переменными. Ниже приведен его пример:

library(lubridate)
df <- tibble(DateTime = ymd_hms(c("2020-04-06 10:00:00", 
                                                    "2020-04-07 12:30:00", 
                                                    "2020-04-07 14:31:00", 
                                                    "2020-05-05 17:00:00")),
                               Var1 = c(1,2,3,4),
                               var2= c("a","b","c","d"))
df
# A tibble: 4 x 3
          DateTime             Var1 var2 
          <dttm>              <dbl> <chr>
        1 2020-04-06 10:00:00     1 a    
        2 2020-04-07 12:30:00     2 b    
        3 2020-04-07 14:31:00     3 c    
        4 2020-05-05 17:00:00     4 d   

Я хотел бы отфильтровать строки так, чтобы он возвращал фрейм данных с элементом времени в DateTime, находящимся между:

  • С 09:15:00 до 12:00:00 ИЛИ

  • 13: 15: 00 до 16:30:00 ИЛИ

  • 17: 15: 00 до 01: 00: 00.

Таким образом, он возвращает следующий фрейм данных:

# A tibble: 2 x 3
  DateTime             Var1 var2 
  <dttm>              <dbl> <chr>
1 2020-04-06 10:00:00     1 a    
2 2020-04-07 14:31:00     3 c 

Я знаю, что могу DateTime >= hms("09:15:00") & DateTime <= hms("12:00:00") и так далее, но это кажется слишком сложным . Есть ли способ попроще?

Ответы [ 3 ]

2 голосов
/ 08 мая 2020

Подумав еще немного, вы можете использовать функции interval из lubridate.

К сожалению, они работают только с объектами datetime. Так что вам придется немного взломать и добавить произвольную дату:

library(dplyr)
library(lubridate)
library(purrr)
my.intervals <- c(dmy_hms("1/1/00 09:15:00") %--% dmy_hms("1/1/00 12:00:00"),
                  dmy_hms("1/1/00 13:15:00") %--% dmy_hms("1/1/00 16:30:00"),
                  dmy_hms("1/1/00 17:15:00") %--% dmy_hms("1/1/00 23:59:59"),
                  dmy_hms("1/1/00 00:00:00") %--% dmy_hms("1/1/00 01:00:00"))

df %>%
  mutate(Time = dmy_hms(paste0("01/01/00 ",format(DateTime,"%H:%M:%S")))) %>% 
  dplyr::filter(map_lgl(Time, ~ any(.x %within% my.intervals))) %>%
  dplyr::select(-Time)
# A tibble: 2 x 3
  DateTime             Var1 var2 
  <dttm>              <dbl> <chr>
1 2020-04-06 10:00:00     1 a    
2 2020-04-07 14:31:00     3 c   
1 голос
/ 08 мая 2020

Использование метода «POSIXt» из cut является одним из вариантов:

library(dplyr)

df %>%
  filter(cut(as.POSIXct(paste0(Sys.Date(), format(DateTime, "%H:%M:%S"))), 
             breaks=as.POSIXct(
               c("09:15:00","12:00:00","13:15:00","16:30:00","17:15:00","01:00:00"), 
               format="%H:%M:%S"), labels=FALSE) %in% c(2,4,6))

# A tibble: 2 x 3
  DateTime             Var1 var2 
  <dttm>              <dbl> <chr>
1 2020-04-06 10:00:00     1 a    
2 2020-04-07 14:31:00     3 c 

Немного неуклюже, но нет необходимости в каких-либо внешних пакетах. Возможно, придется отрегулировать разрывы так, чтобы были включены концы, возможно go назад на 1 секунду.

1 голос
/ 08 мая 2020

Попробуйте следующее:

# library(hms) # hms::as.hms
df %>%
  mutate(DT2 = hms::as.hms(DateTime, tz = "UTC")) %>%
  filter(between(DT2, hms("09:15:00"), hms("12:00:00")) |
           between(DT2, hms("13:15:00"), hms("16:30:00")) |
           DT2 > hms("17:15:00") | DT2 < hms("01:00:00"))
# # A tibble: 2 x 4
#   DateTime             Var1 var2  DT2   
#   <dttm>              <dbl> <chr> <time>
# 1 2020-04-06 10:00:00     1 a     10:00 
# 2 2020-04-07 14:31:00     3 c     14:31 

Вы не можете провести прямое сравнение POSIXt с классом Period lubridate (очевидно). Кроме того, я использовал tz="UTC", поскольку в образцах данных есть один метод определения часового пояса, а в пакете hms должно быть другое предположение. Возможно, вам придется поэкспериментировать с этим аргументом, чтобы убедиться, что он соответствует тому, что вы ожидаете от своих данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...