我正在尝试基于一组基本决策规则来计算两个变量。但是,大多数行的计算取决于其他行中的值,这要求此计算顺序进行。我不知道如何有效地做到这一点(最好是在tidyverse中)。预先感谢!
数据:
数据集的每一行代表一个提交的工作报告。每个报告都嵌套在group
中,其中k
表示该报告在组中的索引,而n
表示在该组中的报告数。 time
是提交的时间戳,length
是工作的大概时间,以分钟为单位,wait
表示在开始工作之前是否等待(wait == 1
),或者是否在完成上一个(wait == 0
)后立即开始工作
+-------+---+---+---------------------+--------+------+
| group | k | n | time | length | wait |
+-------+---+---+---------------------+--------+------+
| A | 1 | 5 | 2017-10-17 12:43:29 | 17.5 | 1 |
| A | 2 | 5 | 2017-10-17 12:44:52 | 45.5 | 0 |
| A | 3 | 5 | 2017-10-17 12:45:58 | 17.5 | 1 |
| A | 4 | 5 | 2017-10-17 13:45:31 | 5 | 1 |
| A | 5 | 5 | 2017-10-17 13:46:48 | 17.5 | 0 |
| B | 1 | 3 | 2017-11-14 12:07:18 | 45.5 | 1 |
| B | 2 | 3 | 2017-11-14 12:14:43 | 45.5 | 1 |
| B | 3 | 3 | 2017-11-14 12:17:45 | 45.5 | 1 |
+-------+---+---+---------------------+--------+------+
编辑:可导入数据示例
structure(list(group = c("A", "A", "A", "A", "A", "B", "B", "B"
), k = c(1L, 2L, 3L, 4L, 5L, 1L, 2L, 3L), n = c(5L, 5L, 5L, 5L,
5L, 3L, 3L, 3L), time = structure(c(1508258609.388, 1508258692.614,
1508258758.234, 1508262331.385, 1508262408.434, 1510679238.849,
1510679683.961, 1510679865.964), class = c("POSIXct", "POSIXt"
), tzone = "America/New_York"), length = c(17.5, 45.5, 17.5, 5, 17.5, 45.5, 45.5,
45.5), wait = c(1, 0, 1, 1, 0, 1, 1, 1)), row.names = c(NA, -8L
), class = "data.frame")
我正在尝试计算两个新值:start
和end
,这是每个提交的作品的开始和结束时间。有数千行,所以我正在寻找一种有效的解决方案。
决策逻辑:
如果报告是该组中的最后一个(k == n
)
end = time
start = end - length
如果报告不是最近的报告,然后是不等待报告(k < n & lead(wait) == 0
)
end = lead(start) - 1
start = end - length
如果报告不是最近的报告,然后是涉及等待的报告(k < n & lead(wait) == 1
)
end = lead(start) - 0.5 * length
start = end - length
这样,计算将从每个组中的最后一个报告开始,然后向后循环遍历直到第一行。
所需的输出:
+-------+---+---+---------------------+--------+------+----------+----------+
| group | k | n | time | length | wait | end | start |
+-------+---+---+---------------------+--------+------+----------+----------+
| A | 1 | 5 | 2017-10-17 12:43:29 | 17.5 | 1 | 11:47:48 | 11:30:18 |
| A | 2 | 5 | 2017-10-17 12:44:52 | 45.5 | 0 | 12:34:18 | 11:48:48 |
| A | 3 | 5 | 2017-10-17 12:45:58 | 17.5 | 1 | 13:14:33 | 12:57:03 |
| A | 4 | 5 | 2017-10-17 13:45:31 | 5 | 1 | 13:28:18 | 13:23:18 |
| A | 5 | 5 | 2017-10-17 13:46:48 | 17.5 | 0 | 13:46:48 | 13:29:18 |
| B | 1 | 3 | 2017-11-14 12:07:18 | 45.5 | 1 | 10:01:15 | 9:15:45 |
| B | 2 | 3 | 2017-11-14 12:14:43 | 45.5 | 1 | 11:09:30 | 10:24:00 |
| B | 3 | 3 | 2017-11-14 12:17:45 | 45.5 | 1 | 12:17:45 | 11:32:15 |
+-------+---+---+---------------------+--------+------+----------+----------+
答案 0 :(得分:0)
这是一种没有循环的整理方法。
在绘制图片之后,我意识到每个报告的开始只是从组的末尾推迟,该报告要么增加零缓冲(如果是最后一个),要么增加1分钟(如果以下报告没有等待) )或当前报告长度的一半(如果等待以下报告)。
因此,如果我们颠倒顺序,我们只需要跟踪为每行添加多少延迟,将其添加到每个长度,然后取这些延迟的累加和即可。那就是从组的结束时间中减去的时间(按此顺序是每个组第一行中的time
)。
output <- df %>%
arrange(group, -k) %>%
group_by(group) %>%
mutate(wait = as.logical(wait)) %>%
mutate(delay = case_when(k == n ~ 0,
# is *next* rpt no wait? (use lag since order reversed)
lag(!wait) ~ 1,
TRUE ~ 0.5 * length),
pushback_alone = length + delay,
pushback_cumul = cumsum(pushback_alone),
# So the last shall be first, and the first last...
start = first(time) - seconds(pushback_cumul*60),
end = start + seconds(length*60)
) %>% ungroup() %>% # EDIT: to make the table ungrouped like it started
arrange(group, k)
结果
output
# A tibble: 8 x 11
# Groups: group [2]
group k n time length wait delay pushback_alone pushback_cumul start end
<chr> <int> <int> <dttm> <dbl> <lgl> <dbl> <dbl> <dbl> <dttm> <dttm>
1 A 1 5 2017-10-17 12:43:29 17.5 TRUE 1 18.5 136. 2017-10-17 11:30:18 2017-10-17 11:47:48
2 A 2 5 2017-10-17 12:44:52 45.5 FALSE 22.8 68.2 118 2017-10-17 11:48:48 2017-10-17 12:34:18
3 A 3 5 2017-10-17 12:45:58 17.5 TRUE 8.75 26.2 49.8 2017-10-17 12:57:03 2017-10-17 13:14:33
4 A 4 5 2017-10-17 13:45:31 5 TRUE 1 6 23.5 2017-10-17 13:23:18 2017-10-17 13:28:18
5 A 5 5 2017-10-17 13:46:48 17.5 FALSE 0 17.5 17.5 2017-10-17 13:29:18 2017-10-17 13:46:48
6 B 1 3 2017-11-14 12:07:18 45.5 TRUE 22.8 68.2 182 2017-11-14 09:15:45 2017-11-14 10:01:15
7 B 2 3 2017-11-14 12:14:43 45.5 TRUE 22.8 68.2 114. 2017-11-14 10:24:00 2017-11-14 11:09:30
8 B 3 3 2017-11-14 12:17:45 45.5 TRUE 0 45.5 45.5 2017-11-14 11:32:15 2017-11-14 12:17:45