Поиск в R по таблицам данных с условием "IF" - PullRequest
0 голосов
/ 08 января 2019

У меня есть две таблицы данных. Таблица с заказами клиентов (показывает идентификатор клиента и дату заказа, когда была сделана покупка) и таблица с сегментацией клиентов (показывает, в каком сегменте был классифицирован клиент за определенный период времени).

Я хочу добавить сегмент из таблицы данных 2) в качестве новой переменной в таблицу данных 1), но, конечно, во время заказа был только тот сегмент, в котором находился клиент.

Customer_Orders <- data.table(
 customer_ID = c("A", "A"),
 order_date = c("2017-06-30", "2019-07-30")
)
head(Customer_Orders)
  customer_ID order_date
1:           A 2017-06-30
2:           A 2018-07-30


Customer_Segmentation <- data.table(
 customer_ID = c("A", "A", "A"),
 segment = c("1", "2", "3"),
 valid_from = c("2017-01-01", "2018-01-01", "2019-01-01"),
 valid_until = c("2017-12-31", "2018-12-31", "2019-12-31")
)
head(Customer_Segmentation)
   customer_ID segment valid_from valid_until
1:           A       1  2017-01-01 2017-12-31
2:           A       2  2018-01-01 2018-12-31
3:           A       3  2019-01-01 2019-12-31

Это результат, созданный вручную, который я ищу

Result <- data.table(
 customer_ID = c("A", "A"),
 order_date = c("2017-06-30", "2019-07-30"),
 segment = c(1, 3)
)
head(Result)
   customer_ID order_date segment
1:           A 2017-06-30       1
2:           A 2019-07-30       3

В настоящее время мое решение состоит в том, чтобы выполнить правое объединение, чтобы в основном добавить все возможные сегменты к каждой строке в таблице заказов клиентов, а затем исключить все строки, где дата заказа не находится между периодами сегмента. Однако, поскольку мой набор данных огромен, это действительно медленное и громоздкое решение

Ответы [ 3 ]

0 голосов
/ 08 января 2019

Как это?

Ваши данные (фиксированные):

library(tidyverse)
library(lubridate)

Customer_Orders <- tibble(
  customer_ID = c("A", "A"),
  order_date = c("2017-06-30", "2019-07-30"))

Customer_Segmentation <- tibble(
  customer_ID = c("A", "A", "A"),
  segment = c("1", "2", "3"),
  valid_from = c("2017-01-01", "2018-01-01", "2019-01-01"),
  valid_until = c("2017-12-31", "2018-12-31", "2019-12-31"))

Код - первые две таблицы предназначены только для создания дат из исходных таблиц с использованием lubridate. Следующий объединяет все.

Customer_Orders2 <- Customer_Orders %>% 
  mutate(order_date = ymd(order_date))

Customer_Segmentation2 <- Customer_Segmentation %>% 
  mutate(valid_from = ymd(valid_from)) %>% 
  mutate(valid_until = ymd(valid_until))

Customer_Orders_join <- full_join(Customer_Orders2, Customer_Segmentation2)

Выбирает сегменты на основе интервала.

Customer_Orders3 <- Customer_Orders_join %>% 
  filter(order_date %within% interval(valid_from, valid_until))

Это производит:

# A tibble: 2 x 5
  customer_ID order_date segment valid_from valid_until
  <chr>       <date>     <chr>   <date>     <date>     
1 A           2017-06-30 1       2017-01-01 2017-12-31 
2 A           2019-07-30 3       2019-01-01 2019-12-31 
0 голосов
/ 24 января 2019

Вот как бы я подошел к проблеме:

Генерация данных (определяя как правильные Date векторы)

Customer_Orders <- data.table(
  customer_ID = c("A", "A"),
  order_date = as.Date(c("2017-06-30", "2019-07-30"))
)


Customer_Segmentation <- data.table(
  customer_ID = c("A", "A", "A"),
  segment = c("1", "2", "3"),
  valid_from =  as.Date(c("2017-01-01", "2018-01-01", "2019-01-01")),
  valid_until =  as.Date(c("2017-12-31", "2018-12-31", "2019-12-31"))
)

Неэквивалентное обновление Присоединиться, чтобы добавить сегмент

При использовании синтаксиса A[B], поддерживаемого data.table, добавить один столбец из таблицы B в исходную таблицу A относительно просто, используя префикс i. для ссылки на столбцы в B. Оставшаяся часть - это просто оператор on, который можно определить как список, используя запись .() в data.table с любым количеством условий.

Customer_Orders[Customer_Segmentation, segment := i.segment, on = .(customer_ID==customer_ID,
                                                                    order_date>=valid_from,
                                                                    order_date<valid_until)]

print(Customer_Orders)
#   customer_ID order_date segment
#1:           A 2017-06-30       1
#2:           A 2019-07-30       3
0 голосов
/ 08 января 2019

Вероятно, самый простой способ - использовать пакет :

library(sqldf)
sqldf("select * from Customer_Orders
               left join Customer_Segmentation
               on order_date between valid_from and valid_until
               and Customer_Orders.ID = Customer_Segmentation.ID")


# customer_ID order_date customer_ID..3 segment valid_from valid_until
# 1           A 2017-06-31              A       1 2017-01-01  2017-12-31
# 2           A 2019-07-30              A       3 2019-01-01  2019-12-31

Он просто присоединяется к таблицам, если дата попадает в указанный промежуток времени

Но если вы настаиваете на использовании , смотрите ниже;

setkey(Customer_Segmentation,customer_ID,valid_from)
setkey(Customer_Orders,customer_ID,order_date)

 ans <- Customer_Segmentation[Customer_Orders,list(.valid_from=valid_from,
                                                    valid_until,order_date,segment),
                      by=.EACHI,roll=T][,`:=`(.valid_from=NULL)]

 ans


# customer_ID valid_from valid_until order_date segment
# 1:           A 2017-06-31  2017-12-31 2017-06-31       1
# 2:           A 2019-07-30  2019-12-31 2019-07-30       3

Легко избавиться от лишних столбцов, если они нежелательны.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...