2016-05-27 2 views
6

У меня есть набор данных, который выглядит следующим образом:Дата наматывания в R

ID FromDate ToDate SiteID Cost 
    1 8/12/2014 8/31/2014 12 245.98 
    1 9/1/2014 9/7/2014 12 269.35 
    1 10/10/2014 10/17/2014 12 209.98 
    1 11/22/2014 11/30/2014 12 309.12 
    1 12/1/2014 12/11/2014 12 202.14 
    2 8/16/2014 8/21/2014 12 109.35 
    2 8/22/2014 8/24/2014 14 44.12 
    2 9/25/2014 9/29/2014 12 98.75 
    3 9/15/2014 9/30/2014 23 536.27 
    3 10/1/2014 10/31/2014 12 529.87 
    3 11/1/2014 11/30/2014 12 969.55 
    3 12/1/2014 12/12/2014 12 607.35 

То, что я хотел бы, чтобы выглядеть как это:

ID FromDate ToDate SiteID Cost 
    1 8/12/2014 9/7/2014 12 515.33 
    1 10/10/2014 10/17/2014 12 209.98 
    1 11/22/2014 12/11/2014 12 511.26 
    2 8/16/2014 8/21/2014 12 109.35 
    2 8/22/2014 8/24/2014 14 44.12 
    2 9/25/2014 9/29/2014 12 98.75 
    3 9/15/2014 9/30/2014 23 536.27 
    3 10/1/2014 12/12/2014 12 2106.77 

Как можно видеть, даты свертываются, если есть продолжение, а затраты суммируются по идентификатору и SiteID. Чтобы помочь кому-то понять сложность, если есть продолжение в интервале дат, но SiteID изменяется, то это отдельная строка. Если в интервале дат нет продолжения, это отдельная строка. Как это сделать в R? Кроме того, у меня более 100 000 индивидуальных идентификаторов. Итак, каков наиболее эффективный способ/пакет для этого?

ответ

6

Это может сделать

df %>% 
    mutate(gr = cumsum(FromDate-lag(ToDate, default=1) != 1)) %>% 
    group_by(gr, ID, SiteID) %>% 
    summarise(FromDate = min(FromDate), 
      ToDate = max(ToDate), 
      cost  = sum(Cost)) 


    gr ID SiteID FromDate  ToDate cost 
    (int) (int) (int)  (date)  (date) (dbl) 
1  1  1  12 2014-08-12 2014-09-07 515.33 
2  2  1  12 2014-10-10 2014-10-17 209.98 
3  3  1  12 2014-11-22 2014-12-11 511.26 
4  4  2  12 2014-08-16 2014-08-21 109.35 
5  4  2  14 2014-08-22 2014-08-24 44.12 
6  5  2  12 2014-09-25 2014-09-29 98.75 
7  6  3  23 2014-09-15 2014-09-30 536.27 
8  6  3  12 2014-10-01 2014-12-12 2106.77 

с data.table

library(data.table) 
setDT(df) 
df[, gr := cumsum(FromDate - shift(ToDate, fill=1) != 1), 
    ][, list(FromDate=min(FromDate), ToDate=max(ToDate), cost=sum(Cost)), by=.(gr, ID, SiteID)] 



    gr ID SiteID FromDate  ToDate cost 
1: 1 1  12 2014-08-12 2014-09-07 515.33 
2: 2 1  12 2014-10-10 2014-10-17 209.98 
3: 3 1  12 2014-11-22 2014-12-11 511.26 
4: 4 2  12 2014-08-16 2014-08-21 109.35 
5: 4 2  14 2014-08-22 2014-08-24 44.12 
6: 5 2  12 2014-09-25 2014-09-29 98.75 
7: 6 3  23 2014-09-15 2014-09-30 536.27 
8: 6 3  12 2014-10-01 2014-12-12 2106.77 
+1

Мне нравится этот подход намного лучше - как насчет упрощения: 'df%>% mutate (crit = FromDate-lag (ToDate, default = 1) == 1, gr = cumsum (crit == FALSE))% >% group_by (гр, ID, SiteID)%>% реферирования (стоимость = сумма (стоимость), FromDate = мин (FromDate), ToDate = макс (ToDate)) ' – JasonAizkalns

+0

Почему падение этот код«ИД «Колонка? – akash87

+0

@JasonAizkalns Спасибо. Это явно лучше. – Khashaa

2

Вот один из способов с dplyr и tidyr - возможно, это несколько возможностей для его очистки, но предпосылка заключается в создании нового группового индикатора. Кто-то с лучшими навыками data.table, вероятно, может придумать что-то красивое для этого.

library(dplyr) 
library(tidyr) 

df$FromDate <- lubridate::mdy(df$FromDate) 
df$ToDate <- lubridate::mdy(df$ToDate) 

gather(df, Date, Val, -c(ID, SiteID, Cost)) %>% 
    arrange(ID, SiteID, Val, Date) %>% 
    group_by(ID, SiteID) %>% 
    mutate(lagDateDiff = as.integer(Val - lag(Val)), 
     indicator = ifelse(Date == "ToDate" | is.na(lagDateDiff), 0, 
          ifelse((Date == "FromDate" & lagDateDiff == 1), 0, 1)), 
     newGroup = cumsum(indicator)) %>% # Run to here to see intermediate result 
    select(-lagDateDiff, -indicator) %>% 
    spread(Date, Val) %>% 
    group_by(ID, SiteID, newGroup) %>% 
    summarise(Min_From_Date = min(FromDate), 
      Max_To_Date = max(ToDate), 
      Sum_Cost = sum(Cost)) 

#  ID SiteID newGroup Min_From_Date Max_To_Date Sum_Cost 
# (int) (int) (dbl)  (date)  (date) (dbl) 
# 1  1  12  0 2014-08-12 2014-09-07 515.33 
# 2  1  12  1 2014-10-10 2014-10-17 209.98 
# 3  1  12  2 2014-11-22 2014-12-11 511.26 
# 4  2  12  0 2014-08-16 2014-08-21 109.35 
# 5  2  12  1 2014-09-25 2014-09-29 98.75 
# 6  2  14  0 2014-08-22 2014-08-24 44.12 
# 7  3  12  0 2014-10-01 2014-12-12 2106.77 
# 8  3  23  0 2014-09-15 2014-09-30 536.27 
+0

Я не знаком с%>% нотации. Не могли бы вы предоставить ссылку или некоторую документацию по этому поводу? – akash87

+0

'%>%' поступает из пакета '' magrittr'' (https://cran.r-project.org/web/packages/magrittr/vignettes/magrittr.html). Короче говоря, он известен как «трубе» -подобный оператор, с помощью которого вы передаете значение вперед в выражение или вызов. Вместо 'f (x)' мы можем написать 'x%>% f', что упрощает чтение и обслуживание определенных цепочек кода. – JasonAizkalns

Смежные вопросы