dplyr :: lag()的反向函数,该函数根据数据返回偏移量

时间:2018-10-20 15:15:45

标签: r dplyr

我有一个有关简单订单处理系统的数据,其中包含每日已完成和已完成订单的数量。以下是一些简化的数据:

Date <- seq(as.Date('2018-01-01'), as.Date('2018-01-10'), by = "day")
In <- c(10, 6, 9, 5, 8, 4, 7, 12, 9, 7)
Out <- c(4, 7, 3, 8, 5, 6, 3, 9, 7, 4)
df <- data.frame(Date, In, Out)

对于我要计算的每个日期:

  1. 正在进行的工作。
  2. 仍在进行中的最旧订单的历史到达日期。

订单处理遵循“先进先出”规则。我们假设系统从上一个期间的10个待处理订单开始。然后,使用dplyr可以很容易地计算出正在进行的工作WIP

df <- df %>% mutate(In.cumul = 10 + cumsum(In),
                Out.cumul = cumsum(Out),
                WIP = In.cumul - Out.cumul)

此输出的引导:

         Date In Out In.cumul Out.cumul WIP
1  2018-01-01 10   4       20         4  16
2  2018-01-02  6   7       26        11  15
3  2018-01-03  9   3       35        14  21
4  2018-01-04  5   8       40        22  18
5  2018-01-05  8   5       48        27  21
6  2018-01-06  4   6       52        33  19
7  2018-01-07  7   3       59        36  23
8  2018-01-08 12   9       71        45  26
9  2018-01-09  9   7       80        52  28
10 2018-01-10  7   4       87        56  31

我的问题是如何实施以上第二部分。计算如下:对于Out.cumul的每个值,查询In_cumul首次达到该值(或刚好高于该值)的日期。

我想避免For循环或创建定制函数,而更喜欢dplyr中的矢量化操作。 dplyr中的lag()lead()最接近,但是偏移量在这里未知,必须根据数据进行计算。因此,这将是某种反向lag()函数。

预期输出是这样:

         Date In Out In.cumul Out.cumul WIP     Oldest
1  2018-01-01 10   4       20         4  16 2018-01-01
2  2018-01-02  6   7       26        11  15 2018-01-01
3  2018-01-03  9   3       35        14  21 2018-01-01
4  2018-01-04  5   8       40        22  18 2018-01-02
5  2018-01-05  8   5       48        27  21 2018-01-03
6  2018-01-06  4   6       52        33  19 2018-01-03
7  2018-01-07  7   3       59        36  23 2018-01-04
8  2018-01-08 12   9       71        45  26 2018-01-05
9  2018-01-09  9   7       80        52  28 2018-01-06
10 2018-01-10  7   4       87        56  31 2018-01-07

非常感谢使用dplyr的优雅解决方案。

2 个答案:

答案 0 :(得分:1)

我们可以使用map中的purrr遍历每个Out.Cuml并找出越过In.cumul的最近日期

library(tidyverse)
df %>%
   mutate(Oldest = Date[as.integer(map(Out.cumul, 
                         function(x) which.max(In.cumul - x >= 0)))])


#         Date In Out In.cumul Out.cumul WIP     Oldest
#1  2018-01-01 10   4       20         4  16 2018-01-01
#2  2018-01-02  6   7       26        11  15 2018-01-01
#3  2018-01-03  9   3       35        14  21 2018-01-01
#4  2018-01-04  5   8       40        22  18 2018-01-02
#5  2018-01-05  8   5       48        27  21 2018-01-03
#6  2018-01-06  4   6       52        33  19 2018-01-03
#7  2018-01-07  7   3       59        36  23 2018-01-04
#8  2018-01-08 12   9       71        45  26 2018-01-05
#9  2018-01-09  9   7       80        52  28 2018-01-06
#10 2018-01-10  7   4       87        56  31 2018-01-07

在基数R中,我们可以使用sapply

使用相同的逻辑
df$Oldest <- df$Date[sapply(df$Out.cumul, function(x) which.max(df$In.cumul - x >= 0))]

答案 1 :(得分:1)

使用findInterval

df %>% 
  mutate(Oldest = Date[findInterval(Out.cumul, In.cumul, left.open = TRUE) + 1])

给予:

         Date In Out In.cumul Out.cumul WIP     Oldest
1  2018-01-01 10   4       20         4  16 2018-01-01
2  2018-01-02  6   7       26        11  15 2018-01-01
3  2018-01-03  9   3       35        14  21 2018-01-01
4  2018-01-04  5   8       40        22  18 2018-01-02
5  2018-01-05  8   5       48        27  21 2018-01-03
6  2018-01-06  4   6       52        33  19 2018-01-03
7  2018-01-07  7   3       59        36  23 2018-01-04
8  2018-01-08 12   9       71        45  26 2018-01-05
9  2018-01-09  9   7       80        52  28 2018-01-06
10 2018-01-10  7   4       87        56  31 2018-01-07