首页 > 解决方案 > dplyr::lag() 的反向函数,它根据数据返回偏移量

问题描述

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

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 个挂单开始。然后很容易WIP用 dplyr 计算正在进行的工作:

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-loops 或创建定制函数,而是更喜欢 dplyr 中的矢量化操作。lag()并且lead()在 dplyr 中最接近,但这里的偏移量是未知的,必须从数据中计算出来。所以这将是某种反向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 的优雅解决方案。

标签: rdplyr

解决方案


利用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

推荐阅读