【问题标题】:How do you replace values in a field with max/min values from other fields subject to particular conditions? Allowing for duplicated conditions如何用受特定条件限制的其他字段的最大值/最小值替换字段中的值?允许重复条件
【发布时间】:2021-10-02 04:54:26
【问题描述】:

这是对上一个问题的扩展:How do you replace values in a field with max/min values from other fields subject to particular conditions?

鉴于Category1Category2TypeIndexDate,我想创建一个名为New_Date 的新字段,如下所示。 New_Date 将是与属于Category1Category2 的每个组合的最高Index 对应的日期,另一个字段Type 等于1。

我的data 有 >1m 条记录和 50 个字段。

注意:与上面链接的其他问题的不同之处在于,Index 字段可能不是唯一的。如果它们重复,我们需要返回最新的max(Date)

Category1 <-c (rep("A",8),rep("B",3),rep("C",4))

Category2 <-c (rep("X",5),rep("Y",4),rep("Z",6))

Index <- c(rep(1,8),seq(1:3),seq(1:4))

Date <- c("01/01/2020","01/02/2020","01/03/2020","01/04/2020","01/05/2020","01/06/2020","01/07/2020","29/07/2020","01/01/2014","01/02/2014","01/01/2015","01/01/2014","01/01/2015","01/01/2016","01/01/2017")

Type <- c(1,2,1,2,2,1,2,1,1,2,1,1,2,2,1)
Category1 Category2 Index Date Type New_Date
A X 1 01/01/2020 1 01/03/2020
A X 2 01/02/2020 2 01/05/2020
A X 1 01/03/2020 1 01/03/2020
A X 4 01/04/2020 2 01/05/2020
A X 5 01/05/2020 2 01/05/2020
A Y 6 01/06/2020 1 29/07/2020
A Y 7 01/07/2020 1 29/07/2020
A Y 8 29/07/2020 1 29/07/2020
B Y 1 01/01/2014 1 01/01/2014
B Z 2 01/02/2014 2 01/01/2015
B Z 3 01/01/2015 1 01/01/2015
C Z 1 01/01/2014 1 01/01/2017
C Z 2 01/01/2015 2 01/01/2017
C Z 3 01/01/2016 2 01/01/2017
C Z 4 01/01/2017 1 01/01/2017

按照Ronak Shah的建议使用下面的代码

setDT(df)[, New_Date := Date[match(max(Index[Type == 1]), Index)], .(Category1, Category2)]

在第三行中,R 将匹配第一个匹配项,New_Date 将是 01/01/2020 而不是 01/03/2020

非常感谢对上述代码的任何建议或细微改动!

【问题讨论】:

  • new_date 的第 1 行和第 3 行是否相同?即第 1 行中的 new_date 应该是 01/01/2020 还是 01/03/2020?
  • 获得预期输出的逻辑有点不清楚。您能否确认new_Date 是否针对预期输出表中最后一行之前的两行正确计算?值不应该是01/01/2016 而不是01/01/2017
  • 问题可能是第 3 行中的“索引”应该是“3”而不是“1”,Index&lt;-c(rep(1,8),seq(1:3),seq(1:4)) 应该是 Index&lt;-c(seq(1,8), seq(1:3), seq(1:4))
  • Eeeek。我很抱歉@Tech Commodities,你说得很对,我使用的代码 sn-p 不正确。应该是Index&lt;-c(1,2,1,4,5,6,7,8, seq(1:3), seq(1:4))。基本上它是先前链接问题的副本,但在第 3 行稍作调整以显示索引字段可以复制。是的,第 1 行和第 3 行的 New_Date 应该是 01/03/2020 是正确的,这就是意图。 @B.ChristianKamgang,是的,你是对的,底行之前的前两行应该是 01/01/2016。道歉

标签: r dataframe data.table


【解决方案1】:

这是使用包data.table 解决问题的一种可能方法。

setDT(df)[, New_Date := max(Date[Index==max(Index)]), by=.(Category1, Category2, Type==1)]
 
#     Category1 Category2 Index       Date  Type   New_Date
#  1:         A         X     1 01/01/2020     1 01/03/2020
#  2:         A         X     2 01/02/2020     2 01/05/2020
#  3:         A         X     1 01/03/2020     1 01/03/2020
#  4:         A         X     4 01/04/2020     2 01/05/2020
#  5:         A         X     5 01/05/2020     2 01/05/2020
#  6:         A         Y     6 01/06/2020     1 29/07/2020
#  7:         A         Y     7 01/07/2020     2 01/07/2020
#  8:         A         Y     8 29/07/2020     1 29/07/2020
#  9:         B         Y     1 01/01/2014     1 01/01/2014
# 10:         B         Z     2 01/02/2014     2 01/02/2014
# 11:         B         Z     3 01/01/2015     1 01/01/2015
# 12:         C         Z     1 01/01/2014     1 01/01/2017
# 13:         C         Z     2 01/01/2015     2 01/01/2016
# 14:         C         Z     3 01/01/2016     2 01/01/2016
# 15:         C         Z     4 01/01/2017     1 01/01/2017

这是dplyr 方法:

df %>%  
  group_by(Category1, Category2, Type==1) %>% 
  mutate(New_Date = max(Date[Index==max(Index)])) %>% 
  ungroup() %>% 
  select(-`Type == 1`)

【讨论】:

    【解决方案2】:

    如果您乐于使用 Tidyverse,我认为这可以满足您的需求:

    df <- tibble::tibble(Category1 = c(rep("A",8),rep("B",3),rep("C",4)),
                 Category2 = c(rep("X",5),rep("Y",4),rep("Z",6)),
                 Index = c(1,2,1,4,5,6,7,8, seq(1:3), seq(1:4)),
                 Date = c("01/01/2020","01/02/2020","01/03/2020","01/04/2020","01/05/2020","01/06/2020","01/07/2020","29/07/2020","01/01/2014","01/02/2014","01/01/2015","01/01/2014","01/01/2015","01/01/2016","01/01/2017"),
                 Type = c(1,2,1,2,2,1,2,1,1,2,1,1,2,2,1)
    
    df |>
      dplyr::group_by(Category1, Category2, Index) |>
      dplyr::mutate(new_date = max(Date))
    
    # A tibble: 15 x 6
    # Groups:   Category1, Category2, Index [14]
       Category1 Category2 Index Date        Type new_date  
       <chr>     <chr>     <dbl> <chr>      <dbl> <chr>     
     1 A         X             1 01/01/2020     1 01/03/2020
     2 A         X             2 01/02/2020     2 01/02/2020
     3 A         X             1 01/03/2020     1 01/03/2020
     4 A         X             4 01/04/2020     2 01/04/2020
     5 A         X             5 01/05/2020     2 01/05/2020
     6 A         Y             6 01/06/2020     1 01/06/2020
     7 A         Y             7 01/07/2020     2 01/07/2020
     8 A         Y             8 29/07/2020     1 29/07/2020
     9 B         Y             1 01/01/2014     1 01/01/2014
    10 B         Z             2 01/02/2014     2 01/02/2014
    11 B         Z             3 01/01/2015     1 01/01/2015
    12 C         Z             1 01/01/2014     1 01/01/2014
    13 C         Z             2 01/01/2015     2 01/01/2015
    14 C         Z             3 01/01/2016     2 01/01/2016
    15 C         Z             4 01/01/2017     1 01/01/2017
              )
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-09-25
      • 2012-12-26
      • 1970-01-01
      • 2017-01-14
      • 1970-01-01
      • 2021-10-13
      • 2015-07-24
      相关资源
      最近更新 更多