r - отсчет часов интервалов по году или дню недели - PullRequest
2 голосов
/ 18 марта 2020

Представьте себе таблицу с датой и часом работы некоторых сотрудников полиции. У нас есть начальная дата-время и конечная дата-время для каждой смены. Я хочу считать часы в год, например. Я могу это сделать, но это довольно сложная задача из-за смены часов в два разных года. Есть ли быстрый способ сделать это? Это довольно распространенная задача, но я не смог найти ни одного пакета для этого. Например, если я хочу посчитать количество часов, отработанных по дням недели, у меня та же проблема. Какие-либо признаки?

Данные:

library(tidyverse)
library(lubridate)

tabela <- tibble(
  data_hora_chegada = c(
    ymd_hms("2018-07-05 18:00:00"),
    ymd_hms("2019-05-05 20:00:00"),
    ymd_hms("2019-12-31 23:00:00")
  ),
  data_hora_saida = c(
    ymd_hms("2018-07-06 16:00:00"),
    ymd_hms("2019-05-05 22:30:00"),
    ymd_hms("2020-01-01 15:00:00")
  )
)

tabela %>%
  mutate(
    intervalo = lubridate::interval(
      data_hora_chegada,
      data_hora_saida
    )
  ) -> tabela

Ожидаемый результат:

Year|Hours
2018| 22
2019| 3,5
2020| 15

# or similarly, with "Day of Week" instead of "Year"

Ответы [ 2 ]

1 голос
/ 18 марта 2020

Чтобы правильно рассчитать с учетом начала года, вам нужно разделить вашу запись на две части, а затем вы можете выполнить вычисление интервал , используя преимущества уже написанного вами кода, а затем выполните суммирование.

tabela.split <-
  tabela %>%
  rowwise() %>%
  do(
    {
      my_row <- .

      new_df <- data.frame(
        Year = year(my_row$data_hora_chegada) : year(my_row$data_hora_saida)
      ) %>%
        mutate(
          data_hora_chegada = ISOdate(Year, 1, 1, 0, 0, 0),
          data_hora_saida = ISOdate(Year+1, 1, 1, 0, 0, 0)
        )

      new_df[1, "data_hora_chegada"] <- my_row$data_hora_chegada
      new_df[nrow(new_df), "data_hora_saida"] <- my_row$data_hora_saida

      new_df
    }
  ) %>%
  ungroup()

print(tabela.split)

Этот код готов к любому интервалу, поэтому, если в этом интервале более двух лет, он сгенерирует столько записей, сколько необходимо для всех лет интервала span.

Выходные данные

   Year data_hora_chegada   data_hora_saida    
* <int> <dttm>              <dttm>             
1  2018 2018-07-05 18:00:00 2018-07-06 16:00:00
2  2019 2019-05-05 20:00:00 2019-05-05 22:30:00
3  2019 2019-12-31 23:00:00 2020-01-01 00:00:00
4  2020 2020-01-01 00:00:00 2020-01-01 15:00:00

Теперь вы можете использовать group_by() и summarize() для получения итогов по годам.

tabela.split %>%
  mutate(
    intervalo = as.numeric(lubridate::interval(
      data_hora_chegada,
      data_hora_saida
    ))
  ) %>%
  group_by(Year) %>%
  summarise(Hours = round(sum(intervalo)/3600,1))

Выходные данные

   Year Hours
  <dbl> <dbl>
1  2018  22  
2  2019   3.5
3  2020  15  

Однако, чтобы разбить его на любую меру времени, как указано динамически, было бы очень сложной задачей.

0 голосов
/ 19 марта 2020

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

# Create a vector of years, from minimum to maximum
all_years <- with(tabela, seq(min(year(data_hora_chegada)), max(year(data_hora_saida))))

# Create list of year intervals for these years
year_intervals <- lapply(all_years, function(x) interval(ymd_hms(paste0(x, "-01-01 00:00:00")), ymd_hms(paste0(x+1, "-01-01 00:00:00"))))
names(year_intervals) <- all_years

# Determine overlap/intersection between single year intervals and tabela intervals
year_overlaps <- lapply(year_intervals, intersect, tabela$intervalo)

# Convert to data frame and sum hours for each year
data.frame(Hours = rowSums(t(sapply(year_overlaps, c)), na.rm = TRUE)/3600)

Вывод

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