Разделение одной строки на несколько строк с ошибкой изменения - PullRequest
0 голосов
/ 12 июня 2018

У меня есть df, похожий на df1, где я хочу разбить строки так, чтобы столбец Hrs_Time_Worked имел интервалы 4, как показано в df2.

Я использовал следующий код, но он выдает ошибку:

df2 = df1 %>%
 group_by(Row)%>%
 mutate(S=START_DATE_TIME,
        Hrs_Time_Worked=list((n<-c(rep(4,Hrs_Time_Worked%/%4),Hrs_Time_Worked%%4))[n!=0]))%>%
 unnest()%>%
 mutate(E=START_DATE_TIME+hours(cumsum(Hrs_Time_Worked)),
        S=E-hours(unlist(Hrs_Time_Worked)),
        START_DATE_TIME=(S),
        END_DATE_TIME=(E),
        S=NULL,E=NULL)

Ошибка в mutate_impl (.data, dots): Ошибка оценки: недопустимый класс Объект Period:периоды должны иметь целочисленные значения.

Требуется следующее:

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

Если есть остаток, который меньше четырех, сумма остатка должна быть указана в последней строке (например, df2; строка 3)

Если дочерняя строка начинается или заканчивается на следующую датустолбец даты должен быть обновлен соответствующим образом (например, df2; строка 2-3)

df1 (текущий)

   Row EMPLID TIME_RPTG_CD START_DATE_TIME     END_DATE_TIME       Hrs_Time_Worked
       <chr>  <chr>        <dttm>              <dttm>                        <dbl>
     1 X00007 REG          2014-07-03 16:00:00 2014-07-03 02:00:00            10.0

df2 (желательно)

Row EMPLID TIME_RPTG_CD START_DATE_TIME     END_DATE_TIME       Hrs_Time_Worked
    <chr>  <chr>        <dttm>              <dttm>                        <dbl>
1   X00007 REG          2014-07-03 16:00:00 2014-07-03 20:00:00            4.0
2   X00007 REG          2014-07-03 20:00:00 2014-07-04 24:00:00            4.0
3   X00007 REG          2014-07-04 24:00:00 2014-07-04 02:00:00            2.0

Ответы [ 2 ]

0 голосов
/ 12 июня 2018

Аналогично @ Prem's, но с использованием столбцов списка и unnest:

df %>% 
  rowwise %>%
  mutate(START_DATE_TIME = list(seq.POSIXt(START_DATE_TIME, END_DATE_TIME, by = "4 hour")),
         END_DATE_TIME = list(c(tail(START_DATE_TIME,-1),END_DATE_TIME))) %>%
  unnest %>%
  mutate(Hrs_Time_Worked = difftime(END_DATE_TIME,START_DATE_TIME, "hours"))

# # A tibble: 3 x 6
#     Row EMPLID TIME_RPTG_CD Hrs_Time_Worked START_DATE_TIME     END_DATE_TIME      
#   <int> <chr>  <chr>        <time>          <dttm>              <dttm>             
# 1     1 X00007 REG          4               2014-07-03 16:00:00 2014-07-03 20:00:00
# 2     1 X00007 REG          4               2014-07-03 20:00:00 2014-07-04 00:00:00
# 3     1 X00007 REG          2               2014-07-04 00:00:00 2014-07-04 02:00:00

Более эффективно использовать map, чем rowwise, хотя, на мой взгляд, менее читабельно, чтобы использовать map youможет сделать это:

df %>% 
  mutate(START_DATE_TIME = map(START_DATE_TIME,~seq.POSIXt(., END_DATE_TIME, by = "4 hour")),
         END_DATE_TIME = map2(END_DATE_TIME,START_DATE_TIME,~c(tail(.y,-1),.x))) %>%
  unnest %>%
  mutate(Hrs_Time_Worked = difftime(END_DATE_TIME,START_DATE_TIME, "hours"))

#   Row EMPLID TIME_RPTG_CD Hrs_Time_Worked     START_DATE_TIME       END_DATE_TIME
# 1   1 X00007          REG         4 hours 2014-07-03 16:00:00 2014-07-03 20:00:00
# 2   1 X00007          REG         4 hours 2014-07-03 20:00:00 2014-07-04 00:00:00
# 3   1 X00007          REG         2 hours 2014-07-04 00:00:00 2014-07-04 02:00:00

В этом случае вывод будет не tibble, а стандарт data.frame, что объясняет, почему столбец Hrs_Time_Worked печатается по-разному.Используйте as_tibble, чтобы получить тот же вывод.Или используйте as.numeric для любого решения, чтобы оно было double.

0 голосов
/ 12 июня 2018

Один из подходов может быть

library(dplyr)
library(tidyr)
library(lubridate)

df %>%
  rowwise() %>%
  mutate(START_DATE_TIME = paste(seq.POSIXt(START_DATE_TIME, END_DATE_TIME, by = "4 hour"), collapse = ",")) %>%
  separate_rows(START_DATE_TIME, sep = ",") %>%
  group_by(Row) %>%
  mutate(END_DATE_TIME   = ymd_hms(lead(START_DATE_TIME, order_by = Row, default = as.character(END_DATE_TIME))),
         START_DATE_TIME = ymd_hms(START_DATE_TIME),
         Hrs_Time_Worked = as.numeric(difftime(END_DATE_TIME, START_DATE_TIME, units = "hour"))) %>%
  filter(Hrs_Time_Worked > 0)

, который дает

    Row EMPLID TIME_RPTG_CD START_DATE_TIME     END_DATE_TIME       Hrs_Time_Worked
1     1 X00007 REG          2014-07-03 16:00:00 2014-07-03 20:00:00            4.00
2     1 X00007 REG          2014-07-03 20:00:00 2014-07-04 00:00:00            4.00
3     1 X00007 REG          2014-07-04 00:00:00 2014-07-04 02:00:00            2.00


Пример данных:

df <- structure(list(Row = 1L, EMPLID = "X00007", TIME_RPTG_CD = "REG", 
    START_DATE_TIME = structure(1404403200, tzone = "UTC", class = c("POSIXct", 
    "POSIXt")), END_DATE_TIME = structure(1404439200, tzone = "UTC", class = c("POSIXct", 
    "POSIXt")), Hrs_Time_Worked = 10), .Names = c("Row", "EMPLID", 
"TIME_RPTG_CD", "START_DATE_TIME", "END_DATE_TIME", "Hrs_Time_Worked"
), row.names = c(NA, -1L), class = "data.frame")

#  Row EMPLID TIME_RPTG_CD     START_DATE_TIME       END_DATE_TIME Hrs_Time_Worked
#1   1 X00007          REG 2014-07-03 16:00:00 2014-07-04 02:00:00              10
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...