根据逻辑条件求和并将值移动到最接近的较小日期

时间:2015-02-04 19:51:07

标签: r data.table dplyr

我有一个数据集testdf(下面的输入),如下所示:

head(testdf)
#        Date ID Value InCalendar
#1 2014-01-01  A     0       TRUE
#2 2014-01-02  A    18       TRUE
#3 2014-01-03  A     0       TRUE
#4 2014-01-04  A    10      FALSE
#5 2014-01-05  A     0      FALSE
#6 2014-01-06  A     6       TRUE
# ... 

最终,我想删除testdf$InCalendarFALSE的所有行。但在删除这些行之前,我想将Value InCalendar FALSE InCalendar TRUE FALSE InCalendar ID InCalendar TRUE InCalendar Date ID FALSE InCalendarlibrary(dplyr) testdf %>% group_by(ID) %>% group_by(InCalendar, grp = cumsum(c(0L, diff(InCalendar)) == 1L), add = TRUE) %>% mutate(Value = ifelse(InCalendar, Value, sum(Value))) %>% group_by(ID, grp) %>% mutate(Value = ifelse(lead(InCalendar), Value, Value + lead(Value, default = 0))) %>% ungroup() %>% filter(InCalendar) %>% select(-grp) #Source: local data frame [48 x 4] # # Date ID Value InCalendar #1 2014-01-01 A 0 TRUE #2 2014-01-02 A 18 TRUE #3 2014-01-03 A 10 TRUE #4 2014-01-06 A 6 TRUE #5 2014-01-07 A 10 TRUE #6 2014-01-08 A 6 TRUE #7 2014-01-09 A 9 TRUE #8 2014-01-10 A 20 TRUE #9 2014-01-14 A 10 TRUE #10 2014-01-15 A 8 TRUE #.. ... .. ... ... dput项之前的行之前。

整个操作需要由testdf <- structure(list(Date = structure(c(16071, 16072, 16073, 16074, 16075, 16076, 16077, 16078, 16079, 16080, 16081, 16082, 16083, 16084, 16085, 16086, 16087, 16088, 16089, 16090, 16091, 16092, 16093, 16094, 16095, 16071, 16072, 16073, 16074, 16075, 16076, 16077, 16078, 16079, 16080, 16081, 16082, 16083, 16084, 16085, 16086, 16087, 16088, 16089, 16090, 16091, 16092, 16093, 16094, 16095, 16071, 16072, 16073, 16074, 16075, 16076, 16077, 16078, 16079, 16080, 16081, 16082, 16083, 16084, 16085, 16086, 16087, 16088, 16089, 16090, 16091, 16092, 16093, 16094, 16095), class = "Date"), ID = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L), .Label = c("A", "B", "C"), class = "factor"), Value = c(0L, 18L, 0L, 10L, 0L, 6L, 10L, 6L, 9L, 0L, 13L, 0L, 7L, 10L, 8L, 3L, 0L, 20L, 0L, 7L, 5L, 4L, 6L, 0L, 12L, 0L, 476L, 48L, 470L, 0L, 166L, 222L, 220L, 219L, 32L, 454L, 0L, 231L, 195L, 205L, 193L, 36L, 474L, 0L, 258L, 239L, 214L, 203L, 29L, 438L, 0L, 98L, 14L, 96L, 0L, 36L, 58L, 46L, 38L, 5L, 90L, 0L, 51L, 49L, 54L, 50L, 7L, 108L, 0L, 55L, 45L, 48L, 35L, 6L, 86L), InCalendar = c(TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE)), class = "data.frame", row.names = c(NA, -75L), .Names = c("Date", "ID", "Value", "InCalendar")) 组完成。

有一个有效的假设,即{{1}}中的第一个条目始终为{{1}},{{1}}条目和{{1}}在所有{{1}}中都相同第

请注意,{{1}}中的{{1}}条目可能会在工作日或周末之后多次出现 - 没有固定的模式。


这就是我想要的,但感觉笨拙并且很长:

{{1}}

我的问题是如何使用基数R或dplyr或data.table以更简洁的方式生成相同的结果。我认为这可能是data.table的滚动连接功能的一个用例,但我对此并不十分熟悉,所以会很感激任何建议。


这是我的测试数据{{1}}:

{{1}}

1 个答案:

答案 0 :(得分:3)

我认为你要比现在更难:

dt = as.data.table(testdf)

dt[, Value := sum(Value), by = list(ID, cumsum(InCalendar))][(InCalendar)]
#         Date ID Value InCalendar
#1: 2014-01-01  A     0       TRUE
#2: 2014-01-02  A    18       TRUE
#3: 2014-01-03  A    10       TRUE
#4: 2014-01-06  A     6       TRUE
#5: 2014-01-07  A    10       TRUE
#...

注意,这会更改原始dt中的值,如果不合适,请使用copy。并且不要忘记在开始之前按日期排序(您的示例数据已经排序)。此外,由于您说自InCalendar始终以每个组中的TRUE开头,如果您的数据按IDDate排序,如示例所示,则不要实际上需要按ID进行分组。