Обратная функция dplyr :: lag (), которая возвращает смещение на основе данных - PullRequest
0 голосов
/ 20 октября 2018

У меня есть данные о простой системе обработки заказов с ежедневным количеством входящих и исходящих завершенных заказов.Вот некоторые упрощенные данные:

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 -Зацикливается или создает сделанную на заказ функцию и вместо этого предпочитает векторизованную операцию в 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.

Ответы [ 2 ]

0 голосов
/ 20 октября 2018

Использование 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
0 голосов
/ 20 октября 2018

Мы можем использовать 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))]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...