2016-05-14 2 views
0

У меня есть кадр данных, называемый DF с столбцами Время и дата. Я хотел бы подмножество DF на основе значений в этих столбцах. Для дат у меня есть список дат в DATES, и я подмножаю строки DF, где DF $ Date присутствует в DATES. На время я хотел бы подмножество с 00:04:00 до 00:06:00. Я не знаю, как это сделать.Подмножество кадра данных на основе временной последовательности

В идеале я хотел бы подмножать оба, указав диапазон, как в 00:04:00 - 00:06:00, а также указав начальную точку и минуты, чтобы посмотреть вперед, как в 00:04: 00 и 3 минуты (два разных метода). Я предполагаю, что все сводится к тому, чтобы сделать последовательность времени и помещать такую ​​последовательность в отдельный вектор, который затем я могу использовать для сопоставления.

Обратите внимание, что это просто короткий воспроизводимый пример. Я ищу общий способ сделать это, потому что на практике я хочу подмножать большие промежутки времени. Также обратите внимание, что хотя в этом примере есть только одна совпадающая дата, на практике будет много подходящих дат, охватывающих несколько лет. Вот почему я считаю, что невозможно использовать POSIXlt для создания временной последовательности. Большое спасибо.

#DF looks like this: 
    #    DateTime XXX  Time  Date 
    #1371 2016-04-25 00:08:00 14 00:08:00 2016-04-25 
    #1372 2016-04-25 00:07:00 13 00:07:00 2016-04-25 
    #1373 2016-04-25 00:06:00 14 00:06:00 2016-04-25 
    #1374 2016-04-25 00:05:00 3 00:05:00 2016-04-25 
    #1375 2016-04-25 00:04:00 2 00:04:00 2016-04-25 
    #1376 2016-04-25 00:03:00 4 00:03:00 2016-04-25 
    #1377 2016-04-25 00:02:00 6 00:02:00 2016-04-25 
    #1387 2016-04-24 23:52:00 41 23:52:00 2016-04-24 
    #1388 2016-04-24 23:51:00 93 23:51:00 2016-04-24 
    #1389 2016-04-24 23:50:00 53 23:50:00 2016-04-24 

    #Code for DF, DATES, and to subset DF based on DATES 
    DF <- structure(list(DateTime = structure(list(sec = c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), min = c(8L, 7L, 6L, 5L, 4L, 3L, 2L, 1L, 0L, 59L, 58L, 57L, 56L, 55L, 54L, 53L, 52L, 51L, 50L), hour = c(0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 23L, 23L, 23L, 23L, 23L, 23L, 23L, 23L, 23L, 23L), mday = c(25L, 25L, 25L, 25L, 25L, 25L, 25L, 25L, 25L, 24L, 24L, 24L, 24L, 24L, 24L, 24L, 24L, 24L, 24L), mon = c(3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L), year = c(116L, 116L, 116L, 116L, 116L, 116L, 116L, 116L, 116L, 116L, 116L, 116L, 116L, 116L, 116L, 116L, 116L, 116L, 116L), wday = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L), yday = c(115L, 115L, 115L, 115L, 115L, 115L, 115L, 115L, 115L, 114L, 114L, 114L, 114L, 114L, 114L, 114L, 114L, 114L, 114L), isdst = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), zone = c("EDT", "EDT", "EDT", "EDT", "EDT", "EDT", "EDT", "EDT", "EDT", "EDT", "EDT", "EDT", "EDT", "EDT", "EDT", "EDT", "EDT", "EDT", "EDT"), gmtoff = c(NA_integer_, NA_integer_, NA_integer_, NA_integer_, NA_integer_, NA_integer_, NA_integer_, NA_integer_, NA_integer_, NA_integer_, NA_integer_, NA_integer_, NA_integer_, NA_integer_, NA_integer_, NA_integer_, NA_integer_, NA_integer_, NA_integer_)), .Names = c("sec", "min", "hour", "mday", "mon", "year", "wday", "yday", "isdst", "zone", "gmtoff"), class = c("POSIXlt", "POSIXt")), Open = c(14, 13, 14, 3, 2, 4, 6, 4, 15, 15, 23, 24, 33, 14, 65, 54, 41, 93, 53), Time = c("00:08:00", "00:07:00", "00:06:00", "00:05:00", "00:04:00", "00:03:00", "00:02:00", "00:01:00", "00:00:00", "23:59:00", "23:58:00", "23:57:00", "23:56:00", "23:55:00", "23:54:00", "23:53:00", "23:52:00", "23:51:00", "23:50:00"), Date = structure(c(16916, 16916, 16916, 16916, 16916, 16916, 16916, 16916, 16916, 16915, 16915, 16915, 16915, 16915, 16915, 16915, 16915, 16915, 16915), class = "Date")), .Names = c("DateTime", "XXX", "Time", "Date"), row.names = c("1371", "1372", "1373", "1374", "1375", "1376", "1377", "1378", "1379", "1380", "1381", "1382", "1383", "1384", "1385", "1386", "1387", "1388", "1389"), class = "data.frame") 
    DATES <- structure(c(12431, 12432, 10445, 10480, 11487, 12494, 12501, 12508, 13115, 13522, 14529, 15536, 16916, 16935), class = "Date") 
    SELEC <- DF[DF$Date %in% DATES,] 

    #Result of subsetting by Date: 
    #     DateTime XXX  Time  Date 
    # 1371 2016-04-25 00:08:00 14 00:08:00 2016-04-25 
    # 1372 2016-04-25 00:07:00 13 00:07:00 2016-04-25 
    # 1373 2016-04-25 00:06:00 14 00:06:00 2016-04-25 
    # 1374 2016-04-25 00:05:00 3 00:05:00 2016-04-25 
    # 1375 2016-04-25 00:04:00 2 00:04:00 2016-04-25 
    # 1376 2016-04-25 00:03:00 4 00:03:00 2016-04-25 
    # 1377 2016-04-25 00:02:00 6 00:02:00 2016-04-25 
    # 1378 2016-04-25 00:01:00 4 00:01:00 2016-04-25 
    # 1379 2016-04-25 00:00:00 15 00:00:00 2016-04-25 

    #How the final product would look like if using a larger data base spanning many years: 
    #   DateTime XXX  Time  Date 
    #2016-04-25 00:06:00 13 00:06:00 2016-04-25 
    #2016-04-25 00:05:00 14 00:05:00 2016-04-25 
    #2016-04-25 00:04:00 3 00:04:00 2016-04-25 
    #2014-03-11 00:06:00 94 00:06:00 2014-03-11 
    #2014-03-11 00:05:00 6 00:05:00 2014-03-11 
    #2014-03-11 00:04:00 14 00:04:00 2014-03-11 
    #2011-08-06 00:06:00 13 00:06:00 2011-08-06 
    #2011-08-06 00:05:00 19 00:05:00 2011-08-06 
    #2011-08-06 00:04:00 41 00:04:00 2011-08-06 

ответ

0

Возможность 1: лексикографическое сравнение

Если все значения времени сохраняются как нулями 24 часа строк с одинаковыми разделителями, например, %H:%M:%S, то для применения фильтра можно использовать лексикографическое сравнение.

DF[DF$Date%in%DATES & DF$Time>='00:04:00' & DF$Time<='00:06:00',]; 
##     DateTime XXX  Time  Date 
## 1373 2016-04-25 00:06:00 14 00:06:00 2016-04-25 
## 1374 2016-04-25 00:05:00 3 00:05:00 2016-04-25 
## 1375 2016-04-25 00:04:00 2 00:04:00 2016-04-25 

Лексикографические решения, конечно, не идеально, потому что они не поддаются времени на основе математики, такие как сложение, вычитание, умножение, деление и т.д.

Лучшие решения включают преобразуя временные значения для числового типа, который кодирует длительность времени как смещение от явного или неопределенного базового времени. Это как популярные библиотеки дата/время кодирования типов, таких как boost date_time для C++, Joda-Time для Java и POSIXct, difftime и lubridate для R.


Возможность 2: ручной цифровой информации

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

hmsToDouble <- function(hms) as.double(substr(hms,1,2))*3600 + as.double(substr(hms,4,5))*60 + as.double(substr(hms,7,8)); 
DF[DF$Date%in%DATES & hmsToDouble(DF$Time)>=hmsToDouble('00:04:00') & hmsToDouble(DF$Time)<=hmsToDouble('00:06:00'),]; 
##     DateTime XXX  Time  Date 
## 1373 2016-04-25 00:06:00 14 00:06:00 2016-04-25 
## 1374 2016-04-25 00:05:00 3 00:05:00 2016-04-25 
## 1375 2016-04-25 00:04:00 2 00:04:00 2016-04-25 

Возможность 3: POSIXt

Мы можем генерировать векторы POSIXt (то есть, POSIXct или POSIXlt) значения и использовать векторизованные сравнения против этих векторов.

DF[DF$Date%in%DATES & DF$DateTime>=as.POSIXct(paste0(DF$Date,' 00:04:00')) & DF$DateTime<=as.POSIXct(paste0(DF$Date,' 00:06:00')),]; 
##     DateTime XXX  Time  Date 
## 1373 2016-04-25 00:06:00 14 00:06:00 2016-04-25 
## 1374 2016-04-25 00:05:00 3 00:05:00 2016-04-25 
## 1375 2016-04-25 00:04:00 2 00:04:00 2016-04-25 

Возможность 4: difftime

только встроенное время типа длительности данных в R является типом difftime, который может быть немного привередливо работать. Но для этой проблемы это довольно просто.

DF[DF$Date%in%DATES & as.difftime(DF$Time)>=as.difftime('00:04:00') & as.difftime(DF$Time)<=as.difftime('00:06:00'),]; 
##     DateTime XXX  Time  Date 
## 1373 2016-04-25 00:06:00 14 00:06:00 2016-04-25 
## 1374 2016-04-25 00:05:00 3 00:05:00 2016-04-25 
## 1375 2016-04-25 00:04:00 2 00:04:00 2016-04-25 

Возможность 5: lubridate

Пакет lubridate широко считаются лучшим пакетом для обработки в R. даты/времени, он обеспечивает тип длительности, которая представляет регулярные продолжительности времени, и тип периода, который позволяет отображать числа различных нерегулярных единиц времени. Исторически, библиотеки даты/времени иногда терпели неудачу, потому что им не хватало понимания различий между нерегулярными периодами времени и продолжительностью продолжительности времени.

В следующем решении hms() вызывает обратные экземпляры типа периода, поэтому мы фактически сравниваем отдельные единицы времени. Кстати, что касается фактического хранения отдельных единиц времени, то дизайн lubridate должен хранить значения секунд как фактическую полезную нагрузку двойного вектора, а остальные единицы (минуты, часы, дни, месяцы и годы) в качестве атрибутов на объект.

library(lubridate); 
DF[DF$Date%in%DATES & hms(DF$Time)>=hms('00:04:00') & hms(DF$Time)<=hms('00:06:00'),]; 
##     DateTime XXX  Time  Date 
## 1373 2016-04-25 00:06:00 14 00:06:00 2016-04-25 
## 1374 2016-04-25 00:05:00 3 00:05:00 2016-04-25 
## 1375 2016-04-25 00:04:00 2 00:04:00 2016-04-25 
0

Как насчет этого?

DF$Time <- strptime(DF$Time,format = '%H:%M:%S') 

timeCondition <- (DF$Time >= strptime('00:04:00',format = '%H:%M:%S')) & (DF$Time <= strptime('00:06:00',format = '%H:%M:%S')) 

SELEC <- DF[timeCondition & DF$Date %in% DATES,] 

Что дает:

   DateTime XXX    Time  Date 
1373 2016-04-25 00:06:00 14 2016-05-14 00:06:00 2016-04-25 
1374 2016-04-25 00:05:00 3 2016-05-14 00:05:00 2016-04-25 
1375 2016-04-25 00:04:00 2 2016-05-14 00:04:00 2016-04-25