【问题标题】:R: how to get last sold out date for each buying?R:如何获得每次购买的最后售罄日期?
【发布时间】:2018-11-21 04:56:18
【问题描述】:

假设我是水果供应商,我有 2 张桌子。 1 用于购买和 1 用于销售,如下所示,

library(tibble)
library(tidyverse)

FruitBought <- tribble(
~name, ~Date, ~Qty,
"Apple", 20180101, 15,
"Apple", 20180105, 20,
"Banana", 20180102, 18,
"Banana", 20180109, 14
)

fruitSold <- tribble(
  ~Date,    ~name,  ~sold,
  20180101, 'Apple',    5,
  20180102, 'Apple',    3,
  20180102, 'Banana',   3,
  20180103, 'Apple',    1,
  20180103, 'Banana',   4,
  20180104, 'Apple',    2,
  20180104, 'Banana',   2,
  20180105, 'Apple',    1,
  20180105, 'Banana',   2,
  20180106, 'Apple',    2,
  20180106, 'Banana',   3,
  20180107, 'Apple',    2,
  20180107, 'Banana',   1,
  20180108, 'Apple',    0,
  20180108, 'Banana',   3,
  20180109, 'Apple',    2,
  20180109, 'Banana',   1,
  20180110, 'Apple',    3,
  20180110, 'Banana',   1
)

我想获得每次购买的最后售罄日期。像这样。

name     | Date     | Qty | LastSoldOut
"Apple"  | 20180101 | 15  | 20180107
"Apple"  | 20180105 | 20  | NA
"Banana" | 20180102 | 18  | 20180109
"Banana" | 20180109 | 14  | NA

有人可以帮忙吗?

【问题讨论】:

  • 选择LastSoldOut日期的逻辑是什么?对于“Apple”,您的日期也大于“20180107”
  • 你需要为每个购买的物品提供一些唯一的标识符,否则对于系统来说一切都是一样的
  • @RonakShah,啊,我的意思是,我在 1 月 1 日买了 15 个苹果,我想知道那 15 个苹果什么时候卖完。

标签: r dplyr data.table


【解决方案1】:

1) 以下是使用data.table non-equi join 的可能方法:

#calculate the available stock at each date
FruitBought[, CumAvail:=cumsum(Qty), by=.(name)]

#calculate the fruits sold up to date
cumsold <- fruitSold[, .(Date, SoldToDate=cumsum(sold)), .(name)]

#use non-equi join to find the first date where 
#sold to date is greater than available stock as per OP
cumsold[
    FruitBought, on=.(name=name, Date>=Date, SoldToDate>CumAvail),
    #for each row in FruitBought, find that first date
    .(Name=i.name, Date=i.Date, Qty, LastSoldOut=x.Date[1L]), by=.EACHI][,
        -(1L:3L)] #remove the joining columns

2)您还可以使用data.tableroll 参数,稍微调整迄今为止的销售数量:

FruitBought[, CumAvail:=cumsum(Qty), by=.(name)]
cumsoldTweak <- fruitSold[, .(Date, SoldToDate=cumsum(sold)-1e-2), .(name)]    
cumsoldTweak[FruitBought, on=c("name", SoldToDate="CumAvail"), roll=-Inf,
    .(name, Date=i.Date, Qty, LastSoldOut=Date)]

输出:

     Name     Date Qty LastSoldOut
1:  Apple 20180101  15    20180107
2:  Apple 20180105  20          NA
3: Banana 20180102  18    20180109
4: Banana 20180109  14          NA

数据:

library(data.table) 
#data.table 1.11.4  Latest news: http://r-datatable.com

FruitBought <- fread("name,Date,Qty
Apple,20180101,15
Apple,20180105,20
Banana,20180102,18
Banana,20180109,14")
#order is important before doing cumsum
setorder(FruitBought, name, Date)

fruitSold <- fread("Date,name,sold
20180101,Apple,5
20180102,Apple,3
20180102,Banana,3
20180103,Apple,1
20180103,Banana,4
20180104,Apple,2
20180104,Banana,2
20180105,Apple,1
20180105,Banana,2
20180106,Apple,2
20180106,Banana,3
20180107,Apple,2
20180107,Banana,1
20180108,Apple,0
20180108,Banana,3
20180109,Apple,2
20180109,Banana,1
20180110,Apple,3
20180110,Banana,1")    
#order is important before doing cumsum
setorder(fruitSold, Date, name)

【讨论】:

  • 它有效。但是我很难理解发生了什么。因为我不熟悉 data.table 包。 cumsold[ FruitBought, on=.(name=name, Date&gt;=Date, SoldToDate&gt;CumAvail), #for each row in FruitBought, find that first date .(Name=i.name, Date=i.Date, Qty, LastSoldOut=x.Date[1L]), by=.EACHI][, -(1L:3L)] #remove the joining columns 上的 :D 是加入的语法。我会先尝试理解你的代码。顺便说一句,您的代码有效,我想说声谢谢。请注意,
【解决方案2】:

你可以做这样的事情来获得想要的输出

    library(tibble)
    library(tidyverse)

FruitBought <- tribble(
  ~name, ~Date, ~Qty,~id,
  "Apple", 20180101, 15,1,
  "Apple", 20180105, 20,2,
  "Banana", 20180102, 18,1,
  "Banana", 20180109, 14,2,
)

fruitSold <- tribble(
  ~Date,    ~name,  ~sold,~id,
  20180101, 'Apple',    5,1,
  20180102, 'Apple',    3,1,
  20180102, 'Banana',   3,1,
  20180103, 'Apple',    1,1,
  20180103, 'Banana',   4,1,
  20180104, 'Apple',    2,1,
  20180104, 'Banana',   2,1,
  20180105, 'Apple',    1,1,
  20180105, 'Banana',   2,1,
  20180106, 'Apple',    2,1,
  20180106, 'Banana',   3,1,
  20180107, 'Apple',    2,1,
  20180107, 'Banana',   1,1,
  20180108, 'Apple',    0,2,
  20180108, 'Banana',   3,1,
  20180109, 'Apple',    2,2,
  20180109, 'Banana',   1,1,
  20180110, 'Apple',    3,2,
  20180110, 'Banana',   1,1
)

fruitSold$Date <- lubridate::ymd(fruitSold$Date)
FruitBought$Date <- lubridate::ymd(FruitBought$Date )
colnames(fruitSold)

sold <- as.data.frame(fruitSold %>% group_by(name,id) %>% summarise(last_date = max(Date)))

colnames(sold)
colnames(FruitBought)
final <- left_join(FruitBought,sold, by  = c("name","id"))

【讨论】:

    猜你喜欢
    • 2013-06-06
    • 2019-12-24
    • 1970-01-01
    • 1970-01-01
    • 2018-06-18
    • 2016-10-21
    • 1970-01-01
    • 1970-01-01
    • 2018-01-12
    相关资源
    最近更新 更多