#r
#r
Вопрос:
У меня есть два набора данных, которые выглядят так
df
Region Quarter Review Date
North Q1 2019-02-01
North Q2 2019-05-01
South Q1 2019-01-15
South Q3 2019-08-20
sales
Region Date Sales
North 2019-01-25 20,500
North 2019-01-27 17,450
North 2019-02-01 31,000
North 2019-02-05 16,700
...
South 2019-08-16 2,300
South 2019-08-17 1,560
South 2019-08-20 3,400
South 2019-08-25 7,200
Я хочу создать новый фрейм данных, который принимает ‘df’, добавляет новый столбец Sales, а также выбирает продажи за два дня до и после даты проверки из фрейма данных ‘sales’. Даты в «продажах» не расположены последовательно и являются случайными для разных регионов и кварталов. Результирующий фрейм данных должен выглядеть следующим образом
final df
Region Quarter Review Date Sales
North Q1 2019-01-25 20,500
North Q1 2019-01-27 17,450
North Q1 2019-02-01 31,000
North Q1 2019-02-05 16,700
North Q1 2019-02-07 23,400
...
South Q3 2019-08-16 2,300
South Q3 2019-08-17 1,560
South Q3 2019-08-20 3,400
South Q3 2019-08-25 7,200
South Q3 2019-08-29 4,350
Я могу получить данные о продажах на дату проверки с помощью слияния, но не знаю, как я могу получить даты и продажи выше и ниже из второго фрейма данных.
Ответ №1:
Вы можете попробовать присоединиться df
df2
'Region'
к столбцу by и для каждого Region
, Quarter
и ReviewDate
значение выберите 2 строки выше и ниже, где ReviewDate == Date
.
library(dplyr)
df %>%
left_join(df2, by = 'Region') %>%
group_by(Region, Quarter, ReviewDate) %>%
slice({i <- which(ReviewDate == Date);(i-2):(i 2)})
Ответ №2:
Я уже некоторое время использую самодельную leadlag
функцию, думаю, ее можно использовать здесь. Это позволяет произвольно опережать и отставать.
leadlag <- function(lgl, bef = 1, aft = bef) {
n <- length(lgl)
bef <- min(n, max(0, bef))
aft <- min(n, max(0, aft))
befx <- if (bef > 0) sapply(seq_len(bef), function(b) c(tail(lgl, n = -b), rep(FALSE, b)))
aftx <- if (aft > 0) sapply(seq_len(aft), function(a) c(rep(FALSE, a), head(lgl, n = -a)))
rowSums(cbind(befx, lgl, aftx), na.rm = TRUE) > 0
}
Простой пример:
vec <- 1:20
vec[leadlag(vec %% 10 == 1)] # 1, 11, as well as /- 1
# [1] 1 2 10 11 12
vec[leadlag(vec %% 10 == 1, 2)] # 1, 11, as well as /- 2
# [1] 1 2 9 10 11 12
vec[leadlag(vec %% 10 == 1, 0, 2)] # 1, 11, as well as none before and 2 after
# [1] 1 2 3 11 12 13
В этом приложении, аналогичном @RonakShah,
df %>%
left_join(df2, by = 'Region') %>%
group_by(Region, Quarter, ReviewDate) %>%
filter(leadlag(ReviewDate == Date))