【问题标题】:How can I implement a dynamic count within R without using a for loop?如何在不使用 for 循环的情况下在 R 中实现动态计数?
【发布时间】:2019-05-28 20:32:20
【问题描述】:

我想明确统计在每个 SKU 的第一个和最后一个购买日期之间从公司购买的客户数量。这是在我清楚地计算了 SQL 中给出的每个 SKU 的客户数量(以及找到第一个和最后一个购买日期)之后,

我有成功解决这个问题的代码;但是,它使用了一个 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')

然后我有另一个大约 600 万行长的表,一个选择不同的销售日期和我称为 OrderTable 的 CustomerID。我不能每天总结不同的计数并将它们加在一起,因为这会使在不同日子购买的客户重复计算。我必须使用我在 SKUCount 表中看到的每个 FirstPurchase/LastPurchase 排列重新计算不同的计数。从那里,我使用以下代码计算给定时间范围内的不同客户数量:

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 秒)。有没有更快的方法来计算不同的计数,还是有更聪明的解决方案来解决我的问题?

【问题讨论】:

  • 这听起来像是一个使用 R 中可用的任何 SQL 包的简单解决方案。你可以使用这些吗?有了你所说的那么多数据,如果你还没有提前使用 RDBS,我会感到惊讶。
  • 你能发布一个OrderTable 的例子,这样你就有一个完全可重现的例子吗?

标签: r


【解决方案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,并通过将函数 FUN 应用于其中的每一行来创建一个名为 DateCustomers 的变量:

    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

【讨论】:

  • 对我来说仍然很慢,但尽管如此,这是解决问题的另一个有效方法。非常感谢!
猜你喜欢
  • 2021-05-29
  • 1970-01-01
  • 2018-10-26
  • 2015-01-24
  • 2023-02-05
  • 1970-01-01
  • 2011-02-22
  • 2017-03-30
  • 1970-01-01
相关资源
最近更新 更多