Рассчитать часовые интервалы от начальной / конечной отметки времени в R - PullRequest
1 голос
/ 30 сентября 2019

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

charger_id <- c(1, 1, 2, 3, 4, 4)
start_time <- as_datetime(c("2019-06-13 10:56:36", "2019-06-13 15:56:36", "2019-06-13 17:55:56", "2019-06-13 08:55:27", "2019-06-13 04:25:56", "2019-06-13 12:45:47")) 
end_time <- as_datetime(c("2019-06-13 14:08:10", "2019-06-14 10:15:46", "2019-06-13 23:20:31", "2019-06-13 17:50:51", "2019-06-13 09:20:16", "2019-06-13 19:20:06"))
df <-  data.frame("charger_id" = charger_id, "start_time" = start_time, "end_time" = end_time)

Вот как мои данные структурированы в настоящее время:

charger_id |      start_time     |      end_time       | 
     1     | 2019-06-13 10:56:36 | 2019-06-13 14:08:10 |
     1     | 2019-06-13 15:16:26 | 2019-06-14 10:15:46 |
     2     | 2019-06-13 17:55:56 | 2019-06-13 24:20:31 |
     3     | 2019-06-13 08:55:27 | 2019-06-13 17:50:51 |
     4     | 2019-06-13 04:25:56 | 2019-06-13 09:20:16 |
     4     | 2019-06-13 12:45:47 | 2019-06-13 19:20:06 |

И я хочу рассчитать для каждого сеанса почасовое использование. Столбец time_occupied указывает прошедшее время (в минутах), которое определенное зарядное устройство для определенного сеанса занимало каждый час.

Например, в отношении charger_id = 1 его первый сеанс проходил с 10:56:36 до 14:08:10, так что это 192 минуты, распределенные на 5 часов. Результирующая таблица для этого сеанса должна выглядеть примерно так:

charger_id |         hour        |    time_occupied    |
    ...    |         ...         |          ...        |
     1     | 2019-06-13 08:00:00 |           0         |
     1     | 2019-06-13 09:00:00 |           0         |
     1     | 2019-06-13 10:00:00 |           4         |
     1     | 2019-06-13 11:00:00 |           60        |
     1     | 2019-06-13 12:00:00 |           60        |
     1     | 2019-06-13 13:00:00 |           60        |
     1     | 2019-06-13 14:00:00 |           8         |
     1     | 2019-06-13 15:00:00 |           0         |
    ...    |          ...        |          ...        |

Эта таблица является небольшим снимком очень длинного финального стола, который я ищу. Для каждого charger_id и дня, за который я собрал данные, будут 24-часовые отметки времени (например, 2019-06-13 15:00:00) и столбец time_occupied, указывающий часовую занятость сеанса.

Для получения дополнительной информации,эта ссылка описывает ту же цель, к которой я стремлюсь, но запрашивала SQL: https://community.oracle.com/message/13318002#13318002

1 Ответ

1 голос
/ 30 сентября 2019

Вот решение data.table. Он использует foverlaps, что означает, что любая пара времени запуска / идентификатора зарядного устройства с time_used, равным 0, исключается. Было бы не сложно добавить эти строки обратно, если вы захотите после этого. Он также должен работать быстро для больших наборов данных, так как data.table версия foverlaps довольно быстрая.

library(data.table)
library(lubridate)
charger_id <- c(1, 1, 2, 3, 4, 4)
start_time <- as_datetime(c("2019-06-13 10:56:36", "2019-06-13 15:56:36", "2019-06-13 17:55:56", "2019-06-13 08:55:27", "2019-06-13 04:25:56", "2019-06-13 12:45:47")) 
end_time <- as_datetime(c("2019-06-13 14:08:10", "2019-06-14 10:15:46", "2019-06-13 23:20:31", "2019-06-13 17:50:51", "2019-06-13 09:20:16", "2019-06-13 19:20:06"))
df <-  data.table("charger_id" = charger_id, "start_time" = start_time, "end_time" = end_time)
setkey(df, start_time, end_time)

start <- as_datetime('2019-06-12')
end <- as_datetime('2019-06-14')
times <- seq.POSIXt(start, end, by = 'hour')
df_times <- data.table(start = times[-length(times)], end = times[-1])
setkey(df_times, start, end)

df <- foverlaps(df, df_times, by.x = c('start_time', 'end_time'), by.y = c('start', 'end'))
df[, time_occupied := as.double(difftime(min(.SD[,c(end, end_time)]), max(.SD[,c(start, start_time)]), units = 'mins')), .(start, charger_id)]

df[order(charger_id), .(charger_id, start, time_occupied)]
#>     charger_id               start time_occupied
#>  1:          1 2019-06-13 10:00:00      3.400000
#>  2:          1 2019-06-13 11:00:00     60.000000
#>  3:          1 2019-06-13 12:00:00     60.000000
#>  4:          1 2019-06-13 13:00:00     60.000000
#>  5:          1 2019-06-13 14:00:00      8.166667
#>  6:          1 2019-06-13 15:00:00      3.400000
#>  7:          1 2019-06-13 16:00:00     60.000000
#>  8:          1 2019-06-13 17:00:00     60.000000
#>  9:          1 2019-06-13 18:00:00     60.000000
#> 10:          1 2019-06-13 19:00:00     60.000000
#> 11:          1 2019-06-13 20:00:00     60.000000
#> 12:          1 2019-06-13 21:00:00     60.000000
#> 13:          1 2019-06-13 22:00:00     60.000000
#> 14:          1 2019-06-13 23:00:00     60.000000
#> 15:          2 2019-06-13 17:00:00      4.066667
#> 16:          2 2019-06-13 18:00:00     60.000000
#> 17:          2 2019-06-13 19:00:00     60.000000
#> 18:          2 2019-06-13 20:00:00     60.000000
#> 19:          2 2019-06-13 21:00:00     60.000000
#> 20:          2 2019-06-13 22:00:00     60.000000
#> 21:          2 2019-06-13 23:00:00     20.516667
#> 22:          3 2019-06-13 08:00:00      4.550000
#> 23:          3 2019-06-13 09:00:00     60.000000
#> 24:          3 2019-06-13 10:00:00     60.000000
#> 25:          3 2019-06-13 11:00:00     60.000000
#> 26:          3 2019-06-13 12:00:00     60.000000
#> 27:          3 2019-06-13 13:00:00     60.000000
#> 28:          3 2019-06-13 14:00:00     60.000000
#> 29:          3 2019-06-13 15:00:00     60.000000
#> 30:          3 2019-06-13 16:00:00     60.000000
#> 31:          3 2019-06-13 17:00:00     50.850000
#> 32:          4 2019-06-13 04:00:00     34.066667
#> 33:          4 2019-06-13 05:00:00     60.000000
#> 34:          4 2019-06-13 06:00:00     60.000000
#> 35:          4 2019-06-13 07:00:00     60.000000
#> 36:          4 2019-06-13 08:00:00     60.000000
#> 37:          4 2019-06-13 09:00:00     20.266667
#> 38:          4 2019-06-13 12:00:00     14.216667
#> 39:          4 2019-06-13 13:00:00     60.000000
#> 40:          4 2019-06-13 14:00:00     60.000000
#> 41:          4 2019-06-13 15:00:00     60.000000
#> 42:          4 2019-06-13 16:00:00     60.000000
#> 43:          4 2019-06-13 17:00:00     60.000000
#> 44:          4 2019-06-13 18:00:00     60.000000
#> 45:          4 2019-06-13 19:00:00     20.100000
#>     charger_id               start time_occupied

Создано в 2019-09-30 пакетом Представить (v0.3.0)

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