【问题标题】:Aggregating / rolling up specific records "into" subsequent records将特定记录聚合/汇总到后续记录中
【发布时间】:2021-09-21 14:32:15
【问题描述】:

我正在尝试将具有特定类型的记录聚合到后续记录中。

我有一个类似于以下的数据集:

df_initial <- data.frame("Id" = c(1, 2, 3, 4, 5), 
                         "Qty" = c(105, 110, 100, 115, 120), 
                         "Type" = c("A", "B", "B", "A", "A"), 
                         "Difference" = c(30, 34, 32, 30, 34))

在对 Id 字段进行排序后,我想将 Type = "B" 的记录聚合到 type = "A" 的下一条记录中。

换句话说,我希望创建 df_new,它将 Id 2 和 3 的 QtyDifference 值添加到 Id 4 的 QtyDifference 值中,并标记 Id 4 正在调整(在字段AdjustedFlag)。

df_new <- data.frame("Id" = c(1, 4, 5), 
                     "Qty" = c(105, 325, 120), 
                     "Type" = c("A", "A", "A"), 
                     "Difference" = c(30, 96, 34), 
                     "AdjustedFlag" = c(0, 1, 0))

我非常感谢有关如何在 R 中执行此操作的任何建议或想法,最好使用 data.table

【问题讨论】:

    标签: r data.table


    【解决方案1】:

    data.table 解决方案:

    df_initial[, .(
        Id = Id[.N], Qty = sum(Qty),
        Difference = sum(Difference),
        AdjustedFlag = +(.N > 1)
      ), by = .(grp = rev(cumsum(rev(Type == "A"))))
      ][, grp := NULL][]
    #       Id   Qty Difference AdjustedFlag
    #    <num> <num>      <num>        <int>
    # 1:     1   105         30            0
    # 2:     4   325         96            1
    # 3:     5   120         34            0
    

    【讨论】:

      【解决方案2】:

      这可以通过创建一个新的分组变量来解决,该变量将行分组到您描述的组中,其想法是利用该分组变量进行所需的聚合。

      而不是拥有

      A B B A A
      

      新的分组变量应该如下所示:

      1 2 2 2 3
      

      这不是data.table 解决方案,但可以在此处应用相同的逻辑:

      library(tidyverse)
      
      df_initial |>
        mutate(
          type2 = ifelse(Type == "A", as.numeric(factor(Type)), 0),
          type2 = cumsum(type2),
          type2 = ifelse(Type == "B", NA, type2)
        ) |>
        fill(type2, .direction = "up") |>
        group_by(type2) |>
        summarise(
          id = max(Id),
          Qty = sum(Qty),
          Difference = sum(Difference),
          AdjustedFlag = as.numeric(n() > 1)
        )
      #> # A tibble: 3 × 5
      #>   type2    id   Qty Difference AdjustedFlag
      #>   <dbl> <dbl> <dbl>      <dbl>        <dbl>
      #> 1     1     1   105         30            0
      #> 2     2     4   325         96            1
      #> 3     3     5   120         34            0
      

      【讨论】:

        【解决方案3】:

        使用tidyverse

        df_initial %>% 
          mutate(gn = if_else(lag(Type, default = 'A') == 'B' | Type == 'B', 'B', Type), 
                              gr = cumsum(lag(gn, default = 'A') != gn),
                              adjusted = if_else(lag(Type, default = 'A') == 'B' | Type == 'B', 1, 0)) %>% 
                              group_by(gr) %>% 
          summarise(Id = last(Id),
                    Qty = sum(Qty),
                    Type = 'A', 
                    Difference = sum(Difference), 
                    Adjusted_flg = max(adjusted)) %>% ungroup()
        

        在这里我们创建一个临时数据集,如下所示:

          Id Qty Type Difference gn gr  Adjusted
        1  1 105    A         30  A  0         0
        2  2 110    B         34  B  1         0
        3  3 100    B         32  B  1         0
        4  4 115    A         30  B  1         1
        5  5 120    A         34  A  2         0
        

        并使用它在summarise 中创建我们的最终表。 gr是表示一组值的列,这就是我们group_by它的原因。

        【讨论】:

          猜你喜欢
          • 2019-03-26
          • 2015-08-01
          • 2020-10-09
          • 1970-01-01
          • 2021-02-16
          • 2022-01-20
          • 1970-01-01
          • 1970-01-01
          • 2013-12-19
          相关资源
          最近更新 更多