Вот, возможно, более простое решение, основанное на dplyr
и fuzzyjoin
.
Сначала я определяю день на 90 дней раньше **, а затем присоединяюсь к списку с самим собой, вводя в каждом элементе совпадения дату промоушена, которая составляет «с 90 дней до» и «до текущей даты». Количество строк для каждой Item-Date - это количество рекламных акций в течение 90 дней. Вычитая строку, представляющую себя, мы получаем количество предыдущих повышений.
** «На 90 дней раньше» проще, чем «на 3 месяца раньше», который варьируется по длине и спорен для некоторых дат: что за 3 месяца до 30 мая?
Prep
library(dplyr); library(fuzzyjoin); library(lubridate)
df <- readxl::read_excel(
"~/Downloads/example_20190519.xlsx",
col_types = c("text", "numeric", "date", "numeric"))
df_clean <- df %>% select(-Times.Promoted.Last.3.Months)
Решение
df_clean %>%
mutate(PromotedDate_less90 = PromotedDate - days(90)) %>%
# Pull in all matches (including current row) with matching Item and Promoted Date
# that is between Promoted Date and 90 days prior.
fuzzy_left_join(df_clean,
by = c("ItemName" = "ItemName",
"ItemNumber" = "ItemNumber",
"PromotedDate_less90" = "PromotedDate",
"PromotedDate" = "PromotedDate"),
match_fun = list(`==`, `==`, `<=`, `>=`)
) %>%
group_by(ItemName = ItemName.x,
ItemNumber = ItemNumber.x,
PromotedDate = PromotedDate.x) %>%
summarize(promotions_in_prior_90d = n() - 1) %>%
ungroup()
Вывод (в другом порядке, но соответствует цели)
# A tibble: 12 x 4
ItemName ItemNumber PromotedDate promotions_in_prior_90d
<chr> <dbl> <dttm> <dbl>
1 ItemA 10021 2018-09-19 00:00:00 0
2 ItemA 10021 2018-10-15 00:00:00 1
3 ItemA 10021 2018-11-30 00:00:00 2
4 ItemA 10021 2018-12-31 00:00:00 2
5 itemB 10024 2018-12-15 00:00:00 0
6 ItemB 10024 2018-04-02 00:00:00 0
7 ItemB 10024 2018-06-05 00:00:00 1
8 ItemB 10024 2018-12-01 00:00:00 0
9 ItemC 19542 2018-07-20 00:00:00 0
10 ItemC 19542 2018-11-17 00:00:00 0
11 ItemC 19542 2018-12-01 00:00:00 1
12 ItemC 19542 2018-12-14 00:00:00 2