【问题标题】:Calculating sum based on differences of dates by grouping 2 or more columns通过对 2 列或更多列进行分组来计算基于日期差异的总和
【发布时间】:2019-09-19 22:15:41
【问题描述】:

假设我有一个类似于下面的数据集:

| id   |    Date   | Buyer | diff | Amount | ConsecutiveSum |
|------|:---------:|------:|------|--------|----------------|
| 334  | 6/15/2018 | Simon | NA   | 1948   | 0              |
| 334  | 6/20/2018 | Simon | 5    | 4290   | 6238           |
| 334  | 8/17/2018 | Simon | 58   | 4260   | 8550           |
| 334  | 8/20/2018 | Simon | 3    | 79     | 4339           |
| 334  | 8/7/2018  | Wang  | NA   | 2145   | 0              |
| 334  | 8/9/2018  | Wang  | 2    | 4192   | 6337           |
| 5006 | 3/4/2019  | Wang  | NA   | 1700   | 0              |
| 5006 | 3/7/2019  | Wang  | 3    | 335    | 2035           |
| 5006 | 5/5/2019  | Wang  | 59   | 4400   | 4735           |
| 5006 | 5/9/2019  | Wang  | 4    | 2700   | 7100           |
| 5006 | 5/14/2019 | Wang  | 5    | 4355   | 7055           |
| 5006 | 5/17/2019 | Wang  | 3    | 3100   | 7455           |

我需要获取相同买方和相同 ID 的连续行金额总和 >=5000 但相差 5 天(=5000,而对于 8/17/2018 和 8/ 20/2018 也是 5 天内的差异,但 ConsecutiveSum 不大于或等于 5000(所以,我不希望这些交易出现在输出中)。 此外,王在 2019 年 5 月 5 日和 2019 年 5 月 9 日完成的交易相差 5 天之内,但我只能获得 2019 年 5 月 9 日的交易,而不是 2019 年 5 月 5 日的交易这篇文章Calculate sum of a column if the difference between consecutive rows meets a condition。 如何重组代码以包含此类事务?

下面是代码:

df <- data.frame(id = c("334","334","334","334","334","334","5006","5006","5006","5006","5006","5006"),
      Date = c("6/15/2018","6/20/2018","8/17/2018","8/20/2019","8/7/2018","8/9/2018","3/4/2019",
             "3/7/2019","5/5/2019","5/9/2019","5/14/2019","5/17/2019"), 
      Buyer = c("Simon", "Simon", "Simon", "Simon", "Chang", "Chang", "Chang", "Chang", "Chang",
              "Chang","Chang","Chang"), 
      diff = c("NA","5","58","3","NA","2","NA","3","59","4","5","3"),
      Amount = c("1948","4290","4260","79","2145","4192","1700","335","4400","2700","4355","3100"), 
      ConsecutiveSum = c("0","6238","8550","4339","0","6337","0","2035","4735","7100","7055","7455"),stringsAsFactors = F)  

df$Date <- as.Date(df$Date, '%m/%d/%Y')
df$Amount <- as.numeric(df$Amount)
df$diff <- as.numeric(df$diff)
df$ConsecutiveSum <- as.numeric(df$ConsecutiveSum)

df_sum = df %>% group_by(Buyer,id) %>%
         mutate(rank=dense_rank(Date)) %>%
         mutate(ConsecutiveSum = ifelse(is.na(lag(Amount)),0,Amount  + lag(Amount , default = 0))) %>% 
         filter(diff<=5 & ConsecutiveSum>=5000 | ConsecutiveSum==0 & lead(ConsecutiveSum)>=5000) 

我的预期输出应该如下所示:

| id   |    Date   | Buyer | diff | Amount | ConsecutiveSum |
|------|:---------:|------:|------|--------|----------------|
| 334  | 6/15/2018 | Simon | NA   | 1948   | 0              |
| 334  | 6/20/2018 | Simon | 5    | 4290   | 6238           |
| 334  |  8/7/2018 |  Wang | NA   | 2145   | 0              |
| 334  | 8/9/2018  | Wang  | 2    | 4192   | 6337           |
| 5006 | 5/5/2019  | Wang  | 59   | 4400   | 4735           |
| 5006 | 5/9/2019  | Wang  | 4    | 2700   | 7100           |
| 5006 | 5/14/2019 | Wang  | 5    | 4355   | 7055           |
| 5006 | 5/17/2019 | Wang  | 3    | 3100   | 7455           |

【问题讨论】:

  • 您是否需要rank 中的df_sum
  • @akrun 我认为是因为它会以每个买家订购商品的不同方式排名
  • 在您的预期输出中,第 5 行在ConsecutiveSum 中有一个8592 值。它是从哪里来的?

标签: r filter group-by sum


【解决方案1】:

这是一种使用隐藏变量keep1keep2 的可能性。首先重复示例中的所有行,直到df$ConsecutiveSum &lt;- as.numeric(df$ConsecutiveSum),然后:

df %>% replace_na(list(diff=0)) %>% 
    mutate(keep1=ifelse((ConsecutiveSum>=5000 & diff<=5), 1, 0)) %>% 
    mutate(keep2=ifelse(lead(keep1)==1, 1, 0)) %>% 
    filter(keep1==1|keep2==1) %>% select(-keep1,-keep2)

结果是:

    id       Date Buyer diff Amount ConsecutiveSum
1  334 2018-06-15 Simon    0   1948              0
2  334 2018-06-20 Simon    5   4290           6238
3  334 2018-08-07 Chang    0   2145              0
4  334 2018-08-09 Chang    2   4192           6337
5 5006 2019-05-05 Chang   59   4400           4735
6 5006 2019-05-09 Chang    4   2700           7100
7 5006 2019-05-14 Chang    5   4355           7055
8 5006 2019-05-17 Chang    3   3100           7455

【讨论】:

    【解决方案2】:

    按照您的要求,我想出了一个非常简单的想法,它确实遵循您的逻辑并提供了预期的结果(请注意,您的预期结果的第 5 行并非来自提供的玩具 data.frame)。

    library(data.table)
    
    setDT(df)
    
    # create a column with day differences between consecutive dates of Buyer AND id:
    
    df[, lagdays := c(NA, diff(Date)), by = .(id, Buyer)]
    
    # Filter the cases in which: lagdays are either less than 5 or NA (first row in a Buyer-id combination) AND consecutiveSum is either greater than 5000 OR 0 (first row in a buyer-id combination).
    
    # lagdays := NULL removes the helper variable
    
    df[(lagdays <= 5 | is.na(lagdays)) & (ConsecutiveSum == 0 | ConsecutiveSum >= 5000), ][, lagdays := NULL][]
    
         id       Date Buyer diff Amount ConsecutiveSum
    1:  334 2018-06-15 Simon   NA   1948              0
    2:  334 2018-06-20 Simon    5   4290           6238
    3:  334 2018-08-07 Chang   NA   2145              0
    4:  334 2018-08-09 Chang    2   4192           6337
    5: 5006 2019-03-04 Chang   NA   1700              0
    6: 5006 2019-05-09 Chang    4   2700           7100
    7: 5006 2019-05-14 Chang    5   4355           7055
    8: 5006 2019-05-17 Chang    3   3100           7455
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-03-21
      • 1970-01-01
      • 2023-03-14
      • 2019-06-14
      • 1970-01-01
      • 2013-09-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多