2016-05-27 18 views
6

Tôi có một bộ dữ liệu trông giống như sau:ngày roll-up trong 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 

Những gì tôi muốn này để trông giống như là:

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 

Như người ta có thể thấy, số ngày được cuộn lên nếu có sự tiếp tục và chi phí được tổng hợp bởi ID và SiteID. Để giúp ai đó hiểu được sự phức tạp, nếu có sự tiếp nối trong khoảng thời gian ngày, nhưng SiteID thay đổi, thì đó là một hàng riêng biệt. Nếu không có sự tiếp tục trong khoảng thời gian ngày, nó là một hàng riêng biệt. Làm thế nào để làm điều này trong R? Ngoài ra, tôi có hơn 100.000 ID riêng lẻ. Vì vậy, cách hiệu quả nhất/gói để sử dụng cho điều này là gì?

Trả lời

6

Điều này có thể làm

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 

với 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

Tôi thích cách tiếp cận này tốt hơn rất nhiều - cách đơn giản hóa: 'df%>% biến đổi (crit = FromDate-lag (ToDate, mặc định = 1) == 1, gr = cumsum (crit == FALSE))% >% group_by (gr, ID, SiteID)%>% tóm tắt (cost = sum (Cost), FromDate = min (FromDate), ToDate = max (ToDate)) ' – JasonAizkalns

+0

Tại sao mã này thả" ID " Cột? – akash87

+0

@JasonAizkalns Cảm ơn. Điều đó rõ ràng là tốt hơn. – Khashaa

2

Dưới đây là một cách với dplyrtidyr - có thể là một vài cơ hội để làm sạch điều này, nhưng tiền đề là tạo chỉ báo nhóm mới. Ai đó với một số kỹ năng tốt hơn, có thể có thể đưa ra một cái gì đó khá trơn tru cho một trong những điều này.

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

Tôi không quen thuộc với%>% ký hiệu. Bạn có thể cung cấp một liên kết hoặc một số tài liệu liên quan đến điều này? – akash87

+0

'%>%' xuất phát từ gói ['magrittr'] (https://cran.r-project.org/web/packages/magrittr/vignettes/magrittr.html). Tóm lại, nó được gọi là toán tử "đường ống", mà bạn đặt một giá trị chuyển tiếp vào một biểu thức hoặc cuộc gọi. Thay vì 'f (x)', chúng ta có thể viết 'x%>% f' làm cho các chuỗi mã nhất định dễ đọc và duy trì hơn. – JasonAizkalns

Các vấn đề liên quan