Как динамически условно фильтровать строки в R-кадре данных
Предположим, у меня есть упорядоченный фрейм данных, который выглядит следующим образом:
df <- data.frame(customer = c('cust1','cust1','cust2','cust3','cust3'),
start_month = as.Date(c('2016-03-01','2017-08-01','2016-03-01','2017-07-01','2017-10-01')),
price = c(29,29,59,99,59),
end_month = as.Date(c('2017-08-01',NA,'2017-09-01','2017-09-01',NA)));
Как я могу написать скрипт на R со следующим бизнес-правилом: если клиент закончил и начал в том же месяце, и цена не изменилась, удалите последнюю транзакцию. Иначе, продолжайте транзакцию. Результирующий фрейм данных будет выглядеть так:
new_df <- data.frame( customer = c('cust1','cust2','cust3','cust3'),
start_date = as.Date(c('2016-03-01','2016-03-01','2017-07-01','2017-10-01')),
price = c(29,59,99,59),
end_date = as.Date(c(NA,'2017-09-01','2017-09-01',NA)));
В этом примере cust1's 2017-08-01 игнорируется и отфильтровывается, потому что цена совпадает с их предыдущей транзакцией. Тем не менее, транзакция cust3 сохраняется, потому что цена отличается.
Как я могу сделать это в R?
1 ответ
library(dplyr)
df <- df %>% group_by(customer) %>% mutate(change = lag(price) - price)
> df
# A tibble: 5 x 5
# Groups: customer [3]
customer start_month price end_month change
<fctr> <date> <dbl> <date> <dbl>
1 cust1 2016-03-01 29 2017-08-01 NA
2 cust1 2017-08-01 29 NA 0
3 cust2 2016-03-01 59 2017-09-01 NA
4 cust3 2017-07-01 99 2017-09-01 NA
5 cust3 2017-10-01 59 NA 40
Первой записью для клиента всегда является NA, и мы ее оставим. И мы удалим строки, где цена не изменилась:
df <- df %>% filter(is.na(change) | change != 0)
> df
# A tibble: 4 x 5
# Groups: customer [3]
customer start_month price end_month change
<fctr> <date> <dbl> <date> <dbl>
1 cust1 2016-03-01 29 2017-08-01 NA
2 cust2 2016-03-01 59 2017-09-01 NA
3 cust3 2017-07-01 99 2017-09-01 NA
4 cust3 2017-10-01 59 NA 40
Все в одной команде:
library(dplyr)
df <-
df %>%
group_by(customer) %>%
mutate(change = lag(price) - price) %>%
filter(is.na(change) | change != 0)
РЕДАКТИРОВАТЬ:
Я забыл проверить, не меняется ли дата:
library(dplyr)
df <-
df %>%
group_by(customer) %>%
mutate(change = lag(price) - price) %>%
mutate(date_change = lag(end_month) - start_month) %>%
filter((is.na(change) | change != 0) | (is.na(date_change) | date_change != 0))
это сохранит каждую первую запись и удалит строки, где начальная дата совпадает с предыдущей конечной датой И цена не изменилась.