【问题标题】:dplyr: calculate the days for product replenishmentdplyr:计算产品补货的天数
【发布时间】:2019-10-30 10:42:32
【问题描述】:

我正在处理一个数据集,我需要在其中计算零售店从短缺中补充一些产品需要多长时间,以下是该数据集的最简单形式的快速视图:

Date <- c("2019-1-1","2019-1-2","2019-1-3","2019-1-4","2019-1-5","2019-1-6","2019-1-7","2019-1-8")
Product <- rep("Product A",8)
Net_Available_Qty <- c(-2,-2,10,8,-5,-6,-7,0)
sample_df <- data.frame(Date,Product,Net_Available_Qty)

当 Net_Available_Qty 变为负数时,表示存在短缺。当它变回 0 或正数量时,表示供应已恢复。我需要计算的是我们第一次看到短缺和恢复之间的天数。在这种情况下,第一次缺货需要 2 天才能恢复,而第二次缺货需要 3 天才能恢复。

欢迎使用 tidyverse 解决方案。

【问题讨论】:

    标签: r dplyr tidyverse duration


    【解决方案1】:

    我希望其他人找到更清洁的解决方案。但这会产生diffDate,它分配从负数变为正数/零时的日期差。

    sample_df %>%
      mutate(sign = ifelse(Net_Available_Qty > 0, "pos", ifelse(Net_Available_Qty < 0, "neg", "zero")),
             sign_lag = lag(sign, default = sign[1]),       # get previous value (exception in the first place)
             change = ifelse(sign != sign_lag, 1 , 0),      # check if there's a change
             sequence=sequence(rle(as.character(sign))$lengths)) %>%
      group_by(sequence) %>%
      mutate(diffDate = as.numeric(difftime(Date, lag(Date,1))),
             diffDate=ifelse(Net_Available_Qty <0, NA, ifelse((sign=='pos'| sign=='zero') & sequence==1, diffDate, NA))) %>% 
      ungroup() %>%
      select(Date, Product, Net_Available_Qty, diffDate)
    

    【讨论】:

    • 非常感谢 Schilker 的快速回复。我需要花一些时间来理解你的代码。最令人困惑的部分是:sequence=sequence(rle(as.character(sign))$lengths) 的变异列,你能帮我理解一下吗?
    • @FelixZhao,创建序列变量是为了:计算变量符号的连续出现次数。符号是用于显示 Net_Available_Qty 的负值、正值或零值的创建因子。如果您想查看完整的数据集,请删除上述代码中的“Select()”。它可能会让您更好地理解。
    • 然后我们按顺序分组,因为它第一次出现新的正数、负数或零来:计算第一次出现之间的日期差
    • 嗨 Schilker,你拯救了我的一天!我对您的代码进行了一些修改以适应我的问题,并且效果很好。非常感谢!
    • 不客气@felixZhao,如果您觉得我的回答对您有帮助并解决了您的问题,请将其标记为线程上的正确答案。干杯!
    【解决方案2】:

    @Schilker 使用rle 提出了一个好主意。我正在他的回答的基础上提供一个略短的版本,包括使用cumsum

    Date <- c("2019-1-1","2019-1-2","2019-1-3","2019-1-4","2019-1-5","2019-1-6","2019-1-7","2019-1-8")
    Product <- rep("Product A",8)
    Net_Available_Qty <- c(-2,-2,10,8,-5,-6,-7,0)
    sample_df <- data.frame(Date,Product,Net_Available_Qty)
    
    library(tidyverse)
    
    sample_df %>%
      mutate(
        diffDate = c(1, diff(as.Date(Date))),
        sequence = sequence(rle(Net_Available_Qty >= 0)$lengths),
        group = cumsum(c(TRUE, diff(sequence)) != 1L)
      ) %>%
      group_by(group) %>%
      mutate(n_days = max(cumsum(diffDate)))
    #> # A tibble: 8 x 7
    #> # Groups:   group [4]
    #>   Date     Product   Net_Available_Qty diffDate sequence group n_days
    #>   <fct>    <fct>                 <dbl>    <dbl>    <int> <int>  <dbl>
    #> 1 2019-1-1 Product A                -2        1        1     0      2
    #> 2 2019-1-2 Product A                -2        1        2     0      2
    #> 3 2019-1-3 Product A                10        1        1     1      2
    #> 4 2019-1-4 Product A                 8        1        2     1      2
    #> 5 2019-1-5 Product A                -5        1        1     2      3
    #> 6 2019-1-6 Product A                -6        1        2     2      3
    #> 7 2019-1-7 Product A                -7        1        3     2      3
    #> 8 2019-1-8 Product A                 0        1        1     3      1
    

    reprex package (v0.3.0) 于 2020 年 2 月 23 日创建

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-07-16
      • 1970-01-01
      • 2015-06-23
      • 2021-07-10
      • 1970-01-01
      • 2014-01-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多