Обзор
У меня есть фиктивный набор данных с 20 транзакциями.Каждая транзакция содержит:
- Customer_ID
- Дата (дата покупки)
- Канал (канал покупки, DIRECT или RETAIL)
- Сумма (сумма в долларах)транзакции)
В этих фиктивных данных содержится пять различных идентификаторов Customer_ID.
Все даты в этом фиктивном интервале данных с 01 января 2010 года по 18 октября 2018 года.
Яопределение двух периодов времени на основе константы Promo_Date, где Promo_Date = 01OCT2018:
- T1 = Дата
- T2 = Дата> = Promo_Date
Я хотел бы «свести» эти данные к одной записи для каждого Customer_ID, где рассматриваются канал (DIRECT или RETAIL) и период времени (T1 или T2).Желаемые агрегированные данные содержат следующую структуру:
- Customer_ID
- DIRECT_T1_Last_Date (Дата последней прямой покупки в T1; нет данных, если ее нет)
- DIRECT_T1_Orders (Количество прямых покупокв T1)
- DIRECT_T1_Amount (Сумма суммы прямых покупок в T1)
- RETAIL_T1_Last_Date (Дата последней розничной покупки в T1; нет данных, если ее нет)
- RETAIL_T1_Orders (Number of Retailпокупки в T1)
- RETAIL_T1_Amount (Сумма розничных покупок в T1)
- T2_Amount (сумма в Т2 независимо от канала)
Я могусоздайте желаемый агрегированный фрейм данных, циклически повторяя данные с помощью dplyr (показано ниже) и sqldf (не показано), но эти подходы кажутся слишком ручными по своей природе.Я надеюсь найти более масштабируемое решение, потому что на самом деле для меня нет ничего необычного в том, чтобы создавать гораздо больше агрегаций (больше каналов ... может быть, даже категории продуктов внутри канала) и намного больше переменных внутри каждой агрегации.
Я экспериментировал с пакетами reshape2 и tidyr и убежден, что один (или оба) из них могут предоставить более элегантное решение, но я просто не могу его решить.
Создание фиктивных данных
Customer_ID <- c(1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 5, 5, 5, 5, 5, 5)
Date <- c('2018-07-17', '2018-07-25', '2018-10-04', '2018-07-29', '2018-08-15',
'2018-09-03', '2018-09-30', '2018-10-01', '2018-02-16', '2018-03-27',
'2018-04-30', '2018-10-18', '2018-07-07', '2018-08-24', '2018-01-01',
'2018-01-23', '2018-02-08', '2018-02-27', '2018-03-31', '2018-07-20')
Channel <- c('DIRECT', 'RETAIL', 'DIRECT', 'DIRECT', 'RETAIL', 'DIRECT', 'DIRECT', 'DIRECT', 'DIRECT', 'DIRECT',
'DIRECT', 'RETAIL', 'DIRECT', 'DIRECT', 'RETAIL', 'RETAIL', 'RETAIL', 'DIRECT', 'DIRECT', 'DIRECT')
Amount <- c(118.70, 78.79, 89.99, 69.42, 116.62, 127.11, 86.85, 90.15, 109.37, 121.31,
125.45, 117.89, 90.51, 123.02, 127.66, 120.89, 122.52, 102.76, 72.18, 92.88)
orders <- data.frame(cbind(data.frame(Customer_ID),
data.frame(Date),
data.frame(Channel),
data.frame(Amount)))
rm(Customer_ID, Date, Channel, Amount)
orders <- orders %>%
mutate(Date = as.Date(Date, "%Y-%m-%d"),
Channel = as.character(Channel)
) %>%
arrange(Customer_ID, Date, Channel, Amount)
Фиктивные данные
Customer_ID Date Channel Amount
1 1 2018-07-17 DIRECT 118.70
2 1 2018-07-25 RETAIL 78.79
3 1 2018-10-04 DIRECT 89.99
4 2 2018-07-29 DIRECT 69.42
5 2 2018-08-15 RETAIL 116.62
6 2 2018-09-03 DIRECT 127.11
7 2 2018-09-30 DIRECT 86.85
8 2 2018-10-01 DIRECT 90.15
9 3 2018-02-16 DIRECT 109.37
10 3 2018-03-27 DIRECT 121.31
11 3 2018-04-30 DIRECT 125.45
12 3 2018-10-18 RETAIL 117.89
13 4 2018-07-07 DIRECT 90.51
14 4 2018-08-24 DIRECT 123.02
15 5 2018-01-01 RETAIL 127.66
16 5 2018-01-23 RETAIL 120.89
17 5 2018-02-08 RETAIL 122.52
18 5 2018-02-27 DIRECT 102.76
19 5 2018-03-31 DIRECT 72.18
20 5 2018-07-20 DIRECT 92.88
Определение константы Promo_Date
Promo_Date <- as.Date("2018-10-01", "%Y-%m-%d")
My Long, решение для грубой силы
DIRECT_T1 <- orders %>%
filter(Channel == 'DIRECT' & Date < Promo_Date) %>%
group_by(Customer_ID) %>%
summarise(DIRECT_T1_Last_Date = max(Date),
DIRECT_T1_Orders = n(),
DIRECT_T1_Amount = sum(Amount))
RETAIL_T1 <- orders %>%
filter(Channel == 'RETAIL' & Date < Promo_Date) %>%
group_by(Customer_ID) %>%
summarise(RETAIL_T1_Last_Date = max(Date),
RETAIL_T1_Orders = n(),
RETAIL_T1_Amount = sum(Amount))
T2 <- orders %>%
filter(Date >= Promo_Date) %>%
group_by(Customer_ID) %>%
summarise(T2_Amount = sum(Amount))
Flat_Orders_Long_Way <- full_join(DIRECT_T1, RETAIL_T1, by = "Customer_ID") %>%
full_join(., T2, by = "Customer_ID") %>%
mutate(DIRECT_T1_Orders = ifelse(is.na(DIRECT_T1_Orders) == TRUE, 0, DIRECT_T1_Orders),
DIRECT_T1_Amount = ifelse(is.na(DIRECT_T1_Amount) == TRUE, 0, DIRECT_T1_Amount),
RETAIL_T1_Orders = ifelse(is.na(RETAIL_T1_Orders) == TRUE, 0, RETAIL_T1_Orders),
RETAIL_T1_Amount = ifelse(is.na(RETAIL_T1_Amount) == TRUE, 0, RETAIL_T1_Amount),
T2_Amount = ifelse(is.na(T2_Amount) == TRUE, 0, T2_Amount)) %>%
arrange(Customer_ID)
Flat_Orders_Long_Way <- data.frame(Flat_Orders_Long_Way)
rm(DIRECT_T1, RETAIL_T1, T2)
Желаемые результаты(имена переменных сокращены для этого поста)
compact_output <- Flat_Orders_Long_Way %>%
rename(ID = Customer_ID,
Direct_LDATE = DIRECT_T1_Last_Date,
Direct_Orders = DIRECT_T1_Orders,
Direct_Amount = DIRECT_T1_Amount,
Retail_LDATE = RETAIL_T1_Last_Date,
Retail_Orders = RETAIL_T1_Orders,
Retail_Amount = RETAIL_T1_Amount)
print(compact_output)
ID Direct_LDATE Direct_Orders Direct_Amount Retail_LDATE Retail_Orders Retail_Amount T2_Amount
1 1 2018-07-17 1 118.70 2018-07-25 1 78.79 89.99
2 2 2018-09-30 3 283.38 2018-08-15 1 116.62 90.15
3 3 2018-04-30 3 356.13 <NA> 0 0.00 117.89
4 4 2018-08-24 2 213.53 <NA> 0 0.00 0.00
5 5 2018-07-20 3 267.82 2018-02-08 3 371.07 0.00
Закрытие
Заранее спасибо за вашу помощь!