Как я могу реализовать динамический подсчет в R без использования цикла for?

Я хочу четко подсчитать количество клиентов, которые приобрели у компании между первой и последней датой покупки каждого 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 секунды для каждой строки). Есть ли более быстрый способ подсчета различных счетчиков или есть более умное решение моей проблемы?

Это звучит как простое решение с использованием любого из пакетов SQL, доступных в R. Вы можете их использовать? С таким количеством данных, о котором вы говорите, я был бы удивлен, если бы вы еще не опередили RDBS.

StatsStudent 28.05.2019 22:44

Можете ли вы опубликовать пример OrderTable, чтобы у вас был полностью воспроизводимый пример?

Andrew 29.05.2019 15:37
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
2
119
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Попробуй это:

    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 и создать переменную с именем DateCustomers, применив функцию FUN к каждой ее строке:

    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

Все еще очень медленно с моей стороны, но, тем не менее, это еще одно правильное решение проблемы. Большое спасибо!

Kurtis Ley 29.05.2019 19:54

Другие вопросы по теме