我有一个数据集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$InCalendar
为FALSE
的所有行。但在删除这些行之前,我想将Value
InCalendar
FALSE
InCalendar
TRUE
FALSE
InCalendar
ID
InCalendar
TRUE
InCalendar
Date
ID
FALSE
InCalendar
在library(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}}
答案 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
开头,如果您的数据按ID
和Date
排序,如示例所示,则不要实际上需要按ID
进行分组。