Я хочу четко подсчитать количество клиентов, которые приобрели у компании между первой и последней датой покупки каждого SKU. Это после того, как я четко подсчитал количество клиентов для каждого SKU, указанного в SQL (а также нашел первую и последнюю дату покупки),
У меня есть код, который успешно решает эту проблему; однако он использует цикл for и занимает слишком много времени, потому что существуют десятки тысяч SKU. Это краткий пример того, как выглядит моя таблица SKU:
SKUID <- c('123', '456', '789')
NumberOfCustomers <- c(204543, 92703, 305727)
SKUFirstPurchase <- c('2014-05-02', '2014-02-03', '2016-05-13')
SKULastPurchase <- c('2017-09-30', '2018-07-01', '2019-01-09')
SKUCount <- data.frame(SKUID, NumberOfCustomers,
SKUFirstPurchase, SKULastPurchase)
colnames(SKUCount) <- c('SKU', 'NumberOfCustomers',
'FirstPurchase', 'LastPurchase')
Затем у меня есть еще одна таблица длиной около 6 миллионов строк, выборка отличается от даты продажи и идентификатора клиента, который я называю OrderTable. Я не могу суммировать количество отдельных товаров на ежедневной основе и суммировать их вместе, потому что это приведет к двойному учету клиентов, совершивших покупки в разные дни. Мне приходится пересчитывать количество различных товаров для каждой перестановки FirstPurchase/LastPurchase, которую я вижу в своей таблице SKUCount. Оттуда я использую следующий код для расчета определенного количества клиентов в заданный период времени:
library(dplyr)
for (i in 1:nrow(SKUCount))
{
SKUCount[i, c('DateCustomers')] <-
sapply(OrderTable %>%
filter(Date >= SKUCount[i,'FirstPurchase'],
Date <= SKUCount[i,'LastPurchase']) %>%
select(CustomerID),
function(x) length(unique(x)))
}
Как я уже отмечал ранее, этот фрагмент кода работает, но очень медленно (~ 0,5 секунды для каждой строки). Есть ли более быстрый способ подсчета различных счетчиков или есть более умное решение моей проблемы?
Можете ли вы опубликовать пример OrderTable
, чтобы у вас был полностью воспроизводимый пример?
Попробуй это:
library("purrrlyr")
library("dplyr")
#First creating the datasets including OrderTable (please correct me if I got it wrong!):
SKUID <- c('123', '456', '789')
NumberOfCustomers <- c(204543, 92703, 305727)
SKUFirstPurchase <- c('2014-05-02', '2014-02-03', '2016-05-13')
SKULastPurchase <- c('2017-09-30', '2018-07-01', '2019-01-09')
SKUCount <- data.frame(SKUID, NumberOfCustomers,
SKUFirstPurchase, SKULastPurchase)
colnames(SKUCount) <- c('SKU', 'NumberOfCustomers',
'FirstPurchase', 'LastPurchase')
OrderTable <- data.frame(Date=c('2014-06-02', '2014-08-02', '2015-02-03', '2017-05-13'
,'2015-05-02', '2014-06-03', '2016-07-13', '2017-09-30', '2018-07-01', '2019-01-09'),
CustomerID=c('121','212','3434','24232','121','124','212','131','412','3634'))
#changing factors to date
SKUCount$FirstPurchase<-as.Date(SKUCount$FirstPurchase,format = "%Y-%m-%d")
SKUCount$LastPurchase<-as.Date(SKUCount$LastPurchase,format = "%Y-%m-%d")
OrderTable$Date<-as.Date(OrderTable$Date,format = "%Y-%m-%d")
#defining a function, named FUN, which limit the Date from OrderTable between
#the two date arguments (FirstPurchase and LastPurchase) and returns the
#distinct count of CustomerID's from OrderTable:
FUN <- function(FirstPurchase,LastPurchase){
Rtrn<-OrderTable %>%
filter(Date >= FirstPurchase,
Date <= LastPurchase) %>%
summarize(n_distinct(CustomerID))
as.numeric(Rtrn)
}
SKUCount %>%
rowwise() %>%
mutate(DateCustomers= FUN(FirstPurchase,LastPurchase))
# Source: local data frame [3 x 5]
# Groups: <by row>
#
# # A tibble: 3 x 5
# SKU NumberOfCustomers FirstPurchase LastPurchase DateCustomers
# <fct> <dbl> <date> <date> <dbl>
# 1 123 204543 2014-05-02 2017-09-30 6
# 2 456 92703 2014-02-03 2018-07-01 7
# 3 789 305727 2016-05-13 2019-01-09 5
Все еще очень медленно с моей стороны, но, тем не менее, это еще одно правильное решение проблемы. Большое спасибо!
Это звучит как простое решение с использованием любого из пакетов SQL, доступных в R. Вы можете их использовать? С таким количеством данных, о котором вы говорите, я был бы удивлен, если бы вы еще не опередили RDBS.