Будет ли это работать для вас:
library(dplyr)
library(tidyr)
df <- df %>%
arrange(Group) %>% # for convenience
mutate(Date = as.Date(as.character(Date), "%Y%m%d")) %>% # coerce dates to Date format
group_by(Group) %>%
mutate(DateDiff = Date - lag(Date, 1)) %>% # calculate time difference with previous row
mutate(DateDiff = replace_na(DateDiff, 0)) %>% # replace NA with 0
mutate(DaysLeft = DateDiff - lag(SupplyDays,1)) %>%
mutate(DaysLeft = replace_na(DaysLeft, 0)) %>% # replace NA with 0
mutate(Days = ifelse(lag(DaysLeft, 1) < 0, DaysLeft + lag(DaysLeft, 1), DaysLeft)) %>%
mutate(Days = replace_na(Days, 0)) # replace NA with 0
С этим выводом:
> df
# A tibble: 10 x 6
# Groups: Group [3]
Group Date SupplyDays DateDiff DaysLeft Days
<dbl> <date> <dbl> <drtn> <drtn> <dbl>
1 1 2019-03-09 40 0 days 0 days 0
2 1 2019-05-07 35 59 days 19 days 19
3 1 2019-07-07 2 61 days 26 days 26
4 1 2019-09-07 1 62 days 60 days 60
5 1 2019-10-18 5 41 days 40 days 40
6 2 2019-04-17 7 0 days 0 days 0
7 2 2019-06-10 7 54 days 47 days 47
8 3 2019-01-02 80 0 days 0 days 0
9 3 2019-02-07 9 36 days -44 days -44
10 3 2019-08-08 60 182 days 173 days 129
UPDATE
Я думал об этом на выходных, и это может помочь подойти к этой проблеме иначе. Мы имеем дело с проблемой запасов / потребления, так что вот очень простой подход. У нас должны быть правильные определения, чтобы это работало:
- Входящие: материалы, поступающие в начале периода. Я полагаю, что ваш
SupplyDays
именно такой. - Потребление: в течение периода мы потребляем один день запасов в день
Нам нужно будет рассчитать запасы в конце каждый период. Итак, я создал немного другой фрейм данных со столбцами Date
, Incoming
и Inventory
. Предполагается, что первая строка - это period: 0
только с существующим инвентарем. Тогда Inventory
становится суммой того, что у меня уже есть (data$Inventory [i - 1]
), того, что поступает в этот период (data$Incoming[i]
), и за вычетом того, что я потребляю (as.numeric(data$DateDiff[i])
).
data <- tibble(Date = c(20190309, 20190507, 20190707, 20190907, 20191018, 20191210, 20200120),
Incoming = c(0, 35, 27, 108, 5, 12, 30),
Inventory = c(40, 0, 0, 0, 0, 0, 0))
Это tibble
требует небольшой работы:
data <- data %>%
mutate(Date = as.Date(as.character(Date), "%Y%m%d")) %>%
mutate(DateDiff = Date - lag(Date, 1)) %>%# calculate time difference with previous row
mutate(DateDiff = replace_na(DateDiff, 0))
И поскольку мне нужно обрабатывать первую строку иначе, чем другие строки, мне нужно использовать for-l oop:
for (i in seq_len(nrow(data))) {
if (i == 1) {
data$Inventory [i] <- data$Inventory [i] + data$Incoming[i]
} else {
data$Inventory [i] <- data$Inventory [i - 1] + data$Incoming[i] - as.numeric(data$DateDiff[i])
}
}
С этим выводом:
> data
# A tibble: 7 x 4
Date Incoming Inventory DateDiff
<date> <dbl> <dbl> <drtn>
1 2019-03-09 0 40 0 days
2 2019-05-07 35 16 59 days
3 2019-07-07 27 -18 61 days
4 2019-09-07 108 28 62 days
5 2019-10-18 5 -8 41 days
6 2019-12-10 12 -49 53 days
7 2020-01-20 30 -60 41 days
Это можно легко расширить, чтобы включить группы. Это полезно?