【问题标题】:Calculate and output the date of customer's first order计算并输出客户第一次下单的日期
【发布时间】:2016-10-30 12:27:00
【问题描述】:

数据:

DB <- data.frame(orderID = c(1,2,3,4,4,5,6,6,7,8),    
                 orderDate = c("1.1.12","1.1.12","1.1.12","13.1.12","13.1.12","12.1.12","10.1.12","10.1.12","21.1.12","24.1.12"),
                 itemID = c(2,3,2,5,12,4,2,3,1,5),   
                 customerID = c(1, 2, 3, 1, 1, 3, 2, 2, 1, 1),
                 itemPrice = c(9.99, 14.99, 9.99, 19.99, 29.99, 4.99, 9.99, 14.99, 49.99, 19.99))

预期结果:

DB <- data.frame(orderID = c(1,2,3,4,4,5,6,6,7,8),    
                 orderDate = c("1.1.12","2.1.12","3.1.12","13.1.12","13.1.12","12.1.12","10.1.12","10.1.12","21.1.12","24.1.12"),
                 itemID = c(2,3,2,5,12,4,2,3,1,5),   
                 customerID = c(1, 2, 3, 1, 1, 3, 2, 2, 1, 1),
                 itemPrice = c(9.99, 14.99, 9.99, 19.99, 29.99, 4.99, 9.99, 14.99, 49.99, 19.99),
                 DateOfFirstOrderofCustomer = c("1.1.12", "2.1.12", "3.1.12", "1.1.12", "1.1.12", "3.1.12", "2.1.12", "2.1.12", "1.1.12", "1.1.12"))

为了理解:

orderID 是连续的。同一天从同一customerID 订购的产品将获得相同的orderID。当同一客户在另一天订购产品时,他/她是新的orderID

我想为包含客户第一个订单日期的每一行/条目添加一个额外的列(例如,客户 1 (customerID1) 在1.1.12 下了他的第一个订单,因此在所有订单中都输入了此日期来自该客户)。我们该怎么做?

原始数据大约有 500k 行:所以请给出一个只需要很少性能的解决方案。

【问题讨论】:

  • 您来自数据的orderDate 与预期结果不匹配。希望我的回答通过包含虚拟数据来解决这个问题。
  • 没错 - 我的错误:/

标签: r


【解决方案1】:

仅使用基本 R 函数:

# convert the date column to date-format
DB$orderDate <- as.Date(DB$orderDate, format('%d.%m.%y'))

# get the first date for each customer
DB$DateFirstOrder <- with(DB, ave(orderDate, customerID, FUN = min))

那么结果是(使用 Mike Spencer 的数据):

> DB
   orderID  orderDate itemID customerID itemPrice DateFirstOrder
1        1 2012-01-01      2          1      9.99     2012-01-01
2        2 2012-01-04      3          2     14.99     2012-01-04
3        3 2012-01-06      2          3      9.99     2012-01-06
4        4 2012-01-13      5          1     19.99     2012-01-01
5        4 2012-01-13     12          1     29.99     2012-01-01
6        5 2012-01-12      4          3      4.99     2012-01-06
7        6 2012-01-10      2          2      9.99     2012-01-04
8        6 2012-01-10      3          2     14.99     2012-01-04
9        7 2012-01-21      1          1     49.99     2012-01-01
10       8 2012-01-24      5          1     19.99     2012-01-01

对于最快的解决方案,我会推荐 data.table 包。要使用此包获得所需的结果,您需要执行以下操作:

library(data.table)
setDT(DB)[, orderDate := as.Date(orderDate, format('%d.%m.%y'))
          ][, DateFirstOrder := min(orderDate), by = customerID]

【讨论】:

  • 非常感谢您的支持!我无法检查它今天是否有效:明天早上会检查并给您反馈。
  • @AbsoluteBeginner 很高兴我能帮上忙,如果您有后续问题,可以告诉我。
【解决方案2】:

我更改了您的输入数据,因为您提供的所有数据都具有相同的每位客户首次购买的日期,因此无法判断代码是否有效。该示例使用 dplyr,您也可以使用 tapply,但您需要重新格式化命名向量。

# Dummy data
DB <- data.frame(orderID = c(1,2,3,4,4,5,6,6,7,8),    
                 orderDate = c("1.1.12","4.1.12","6.1.12","13.1.12","13.1.12","12.1.12","10.1.12","10.1.12","21.1.12","24.1.12"),
                 itemID = c(2,3,2,5,12,4,2,3,1,5),   
                 customerID = c(1, 2, 3, 1, 1, 3, 2, 2, 1, 1),
                 itemPrice = c(9.99, 14.99, 9.99, 19.99, 29.99, 4.99, 9.99, 14.99, 49.99, 19.99))

# -------------------------------------------

# Change dates to a readable format
DB$orderDate <- as.Date(DB$orderDate, format="%d.%m.%y")

# -------------------------------------------

library(dplyr)

DB <- DB %>% 
   group_by(customerID) %>% 
   mutate(DateOfFirstOrderofCustomer=min(orderDate))

【讨论】:

  • 非常感谢您的支持!我无法检查它今天是否有效:明天早上会检查并给您反馈。
【解决方案3】:

我正在使用plyr 包。休息一切都是一样的。

DB <- data.frame(orderID = c(1,2,3,4,4,5,6,6,7,8),    
             orderDate = c("1.1.12","4.1.12","6.1.12","13.1.12","13.1.12","12.1.12","10.1.12","10.1.12","21.1.12","24.1.12"),
             itemID = c(2,3,2,5,12,4,2,3,1,5),   
             customerID = c(1, 2, 3, 1, 1, 3, 2, 2, 1, 1),
             itemPrice = c(9.99, 14.99, 9.99, 19.99, 29.99, 4.99, 9.99, 14.99, 49.99, 19.99))


install.packages("plyr")
library(plyr)

DB$orderDate <- as.Date(DB$orderDate, format="%d.%m.%y")
DB = ddply(DB, .(customerID), mutate, DateOfFirstOrderofCustomer = min(orderDate))

【讨论】:

  • 非常感谢您的支持!我无法检查它今天是否有效:明天早上会检查并给您反馈。
猜你喜欢
  • 2016-05-26
  • 2020-01-23
  • 1970-01-01
  • 2021-04-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多